@selfagency/beans-mcp 0.1.4 → 0.5.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 +144 -13
- package/beans-mcp-server.cjs +705 -144
- package/index.cjs +705 -144
- package/index.d.ts +118 -1
- package/index.js +705 -144
- package/package.json +7 -6
package/index.cjs
CHANGED
|
@@ -14433,7 +14433,7 @@ var init_v4 = __esm({
|
|
|
14433
14433
|
}
|
|
14434
14434
|
});
|
|
14435
14435
|
|
|
14436
|
-
// node_modules/.pnpm/@modelcontextprotocol+sdk@1.
|
|
14436
|
+
// node_modules/.pnpm/@modelcontextprotocol+sdk@1.29.0_zod@4.3.6/node_modules/@modelcontextprotocol/sdk/dist/esm/types.js
|
|
14437
14437
|
function assertCompleteRequestPrompt(request) {
|
|
14438
14438
|
if (request.params.ref.type !== "ref/prompt") {
|
|
14439
14439
|
throw new TypeError(`Expected CompleteRequestPrompt, but got ${request.params.ref.type}`);
|
|
@@ -14448,7 +14448,7 @@ function assertCompleteRequestResourceTemplate(request) {
|
|
|
14448
14448
|
}
|
|
14449
14449
|
var LATEST_PROTOCOL_VERSION, SUPPORTED_PROTOCOL_VERSIONS, RELATED_TASK_META_KEY, JSONRPC_VERSION, AssertObjectSchema, ProgressTokenSchema, CursorSchema, TaskCreationParamsSchema, TaskMetadataSchema, RelatedTaskMetadataSchema, RequestMetaSchema, BaseRequestParamsSchema, TaskAugmentedRequestParamsSchema, isTaskAugmentedRequestParams, RequestSchema, NotificationsParamsSchema, NotificationSchema, ResultSchema, RequestIdSchema, JSONRPCRequestSchema, isJSONRPCRequest, JSONRPCNotificationSchema, isJSONRPCNotification, JSONRPCResultResponseSchema, isJSONRPCResultResponse, ErrorCode, JSONRPCErrorResponseSchema, isJSONRPCErrorResponse, JSONRPCMessageSchema, JSONRPCResponseSchema, EmptyResultSchema, CancelledNotificationParamsSchema, CancelledNotificationSchema, IconSchema, IconsSchema, BaseMetadataSchema, ImplementationSchema, FormElicitationCapabilitySchema, ElicitationCapabilitySchema, ClientTasksCapabilitySchema, ServerTasksCapabilitySchema, ClientCapabilitiesSchema, InitializeRequestParamsSchema, InitializeRequestSchema, ServerCapabilitiesSchema, InitializeResultSchema, InitializedNotificationSchema, PingRequestSchema, ProgressSchema, ProgressNotificationParamsSchema, ProgressNotificationSchema, PaginatedRequestParamsSchema, PaginatedRequestSchema, PaginatedResultSchema, TaskStatusSchema, TaskSchema, CreateTaskResultSchema, TaskStatusNotificationParamsSchema, TaskStatusNotificationSchema, GetTaskRequestSchema, GetTaskResultSchema, GetTaskPayloadRequestSchema, GetTaskPayloadResultSchema, ListTasksRequestSchema, ListTasksResultSchema, CancelTaskRequestSchema, CancelTaskResultSchema, ResourceContentsSchema, TextResourceContentsSchema, Base64Schema, BlobResourceContentsSchema, RoleSchema, AnnotationsSchema, ResourceSchema, ResourceTemplateSchema, ListResourcesRequestSchema, ListResourcesResultSchema, ListResourceTemplatesRequestSchema, ListResourceTemplatesResultSchema, ResourceRequestParamsSchema, ReadResourceRequestParamsSchema, ReadResourceRequestSchema, ReadResourceResultSchema, ResourceListChangedNotificationSchema, SubscribeRequestParamsSchema, SubscribeRequestSchema, UnsubscribeRequestParamsSchema, UnsubscribeRequestSchema, ResourceUpdatedNotificationParamsSchema, ResourceUpdatedNotificationSchema, PromptArgumentSchema, PromptSchema, ListPromptsRequestSchema, ListPromptsResultSchema, GetPromptRequestParamsSchema, GetPromptRequestSchema, TextContentSchema, ImageContentSchema, AudioContentSchema, ToolUseContentSchema, EmbeddedResourceSchema, ResourceLinkSchema, ContentBlockSchema, PromptMessageSchema, GetPromptResultSchema, PromptListChangedNotificationSchema, ToolAnnotationsSchema, ToolExecutionSchema, ToolSchema, ListToolsRequestSchema, ListToolsResultSchema, CallToolResultSchema, CompatibilityCallToolResultSchema, CallToolRequestParamsSchema, CallToolRequestSchema, ToolListChangedNotificationSchema, ListChangedOptionsBaseSchema, LoggingLevelSchema, SetLevelRequestParamsSchema, SetLevelRequestSchema, LoggingMessageNotificationParamsSchema, LoggingMessageNotificationSchema, ModelHintSchema, ModelPreferencesSchema, ToolChoiceSchema, ToolResultContentSchema, SamplingContentSchema, SamplingMessageContentBlockSchema, SamplingMessageSchema, CreateMessageRequestParamsSchema, CreateMessageRequestSchema, CreateMessageResultSchema, CreateMessageResultWithToolsSchema, BooleanSchemaSchema, StringSchemaSchema, NumberSchemaSchema, UntitledSingleSelectEnumSchemaSchema, TitledSingleSelectEnumSchemaSchema, LegacyTitledEnumSchemaSchema, SingleSelectEnumSchemaSchema, UntitledMultiSelectEnumSchemaSchema, TitledMultiSelectEnumSchemaSchema, MultiSelectEnumSchemaSchema, EnumSchemaSchema, PrimitiveSchemaDefinitionSchema, ElicitRequestFormParamsSchema, ElicitRequestURLParamsSchema, ElicitRequestParamsSchema, ElicitRequestSchema, ElicitationCompleteNotificationParamsSchema, ElicitationCompleteNotificationSchema, ElicitResultSchema, ResourceTemplateReferenceSchema, PromptReferenceSchema, CompleteRequestParamsSchema, CompleteRequestSchema, CompleteResultSchema, RootSchema, ListRootsRequestSchema, ListRootsResultSchema, RootsListChangedNotificationSchema, ClientRequestSchema, ClientNotificationSchema, ClientResultSchema, ServerRequestSchema, ServerNotificationSchema, ServerResultSchema, McpError, UrlElicitationRequiredError;
|
|
14450
14450
|
var init_types = __esm({
|
|
14451
|
-
"node_modules/.pnpm/@modelcontextprotocol+sdk@1.
|
|
14451
|
+
"node_modules/.pnpm/@modelcontextprotocol+sdk@1.29.0_zod@4.3.6/node_modules/@modelcontextprotocol/sdk/dist/esm/types.js"() {
|
|
14452
14452
|
"use strict";
|
|
14453
14453
|
init_v4();
|
|
14454
14454
|
LATEST_PROTOCOL_VERSION = "2025-11-25";
|
|
@@ -14460,10 +14460,9 @@ var init_types = __esm({
|
|
|
14460
14460
|
CursorSchema = string2();
|
|
14461
14461
|
TaskCreationParamsSchema = looseObject({
|
|
14462
14462
|
/**
|
|
14463
|
-
*
|
|
14464
|
-
* If null, the task has unlimited lifetime until manually cleaned up.
|
|
14463
|
+
* Requested duration in milliseconds to retain task from creation.
|
|
14465
14464
|
*/
|
|
14466
|
-
ttl:
|
|
14465
|
+
ttl: number2().optional(),
|
|
14467
14466
|
/**
|
|
14468
14467
|
* Time in milliseconds to wait between task status requests.
|
|
14469
14468
|
*/
|
|
@@ -14762,7 +14761,11 @@ var init_types = __esm({
|
|
|
14762
14761
|
/**
|
|
14763
14762
|
* Present if the client supports task creation.
|
|
14764
14763
|
*/
|
|
14765
|
-
tasks: ClientTasksCapabilitySchema.optional()
|
|
14764
|
+
tasks: ClientTasksCapabilitySchema.optional(),
|
|
14765
|
+
/**
|
|
14766
|
+
* Extensions that the client supports. Keys are extension identifiers (vendor-prefix/extension-name).
|
|
14767
|
+
*/
|
|
14768
|
+
extensions: record(string2(), AssertObjectSchema).optional()
|
|
14766
14769
|
});
|
|
14767
14770
|
InitializeRequestParamsSchema = BaseRequestParamsSchema.extend({
|
|
14768
14771
|
/**
|
|
@@ -14823,7 +14826,11 @@ var init_types = __esm({
|
|
|
14823
14826
|
/**
|
|
14824
14827
|
* Present if the server supports task creation.
|
|
14825
14828
|
*/
|
|
14826
|
-
tasks: ServerTasksCapabilitySchema.optional()
|
|
14829
|
+
tasks: ServerTasksCapabilitySchema.optional(),
|
|
14830
|
+
/**
|
|
14831
|
+
* Extensions that the server supports. Keys are extension identifiers (vendor-prefix/extension-name).
|
|
14832
|
+
*/
|
|
14833
|
+
extensions: record(string2(), AssertObjectSchema).optional()
|
|
14827
14834
|
});
|
|
14828
14835
|
InitializeResultSchema = ResultSchema.extend({
|
|
14829
14836
|
/**
|
|
@@ -15015,6 +15022,12 @@ var init_types = __esm({
|
|
|
15015
15022
|
* The MIME type of this resource, if known.
|
|
15016
15023
|
*/
|
|
15017
15024
|
mimeType: optional(string2()),
|
|
15025
|
+
/**
|
|
15026
|
+
* The size of the raw resource content, in bytes (i.e., before base64 encoding or any tokenization), if known.
|
|
15027
|
+
*
|
|
15028
|
+
* This can be used by Hosts to display file sizes and estimate context window usage.
|
|
15029
|
+
*/
|
|
15030
|
+
size: optional(number2()),
|
|
15018
15031
|
/**
|
|
15019
15032
|
* Optional annotations for the client.
|
|
15020
15033
|
*/
|
|
@@ -22747,7 +22760,7 @@ var init_utils = __esm({
|
|
|
22747
22760
|
});
|
|
22748
22761
|
|
|
22749
22762
|
// src/internal/graphql.ts
|
|
22750
|
-
var LIST_BEANS_QUERY, CREATE_BEAN_MUTATION, UPDATE_BEAN_MUTATION, DELETE_BEAN_MUTATION;
|
|
22763
|
+
var LIST_BEANS_QUERY, CREATE_BEAN_MUTATION, UPDATE_BEAN_MUTATION, UPDATE_BEAN_MUTATION_WITH_IF_MATCH, DELETE_BEAN_MUTATION, LIST_BEANS_TIMESTAMPS_QUERY;
|
|
22751
22764
|
var init_graphql = __esm({
|
|
22752
22765
|
"src/internal/graphql.ts"() {
|
|
22753
22766
|
"use strict";
|
|
@@ -22765,11 +22778,21 @@ var init_graphql = __esm({
|
|
|
22765
22778
|
mutation($id: ID!, $input: UpdateBeanInput!) {
|
|
22766
22779
|
updateBean(id: $id, input: $input) { id slug path title body status type priority tags parentId blockingIds blockedByIds createdAt updatedAt etag }
|
|
22767
22780
|
}
|
|
22781
|
+
`;
|
|
22782
|
+
UPDATE_BEAN_MUTATION_WITH_IF_MATCH = `
|
|
22783
|
+
mutation($id: ID!, $input: UpdateBeanInput!, $ifMatch: String!) {
|
|
22784
|
+
updateBean(id: $id, input: $input, ifMatch: $ifMatch) { id slug path title body status type priority tags parentId blockingIds blockedByIds createdAt updatedAt etag }
|
|
22785
|
+
}
|
|
22768
22786
|
`;
|
|
22769
22787
|
DELETE_BEAN_MUTATION = `
|
|
22770
22788
|
mutation($id: ID!) {
|
|
22771
22789
|
deleteBean(id: $id)
|
|
22772
22790
|
}
|
|
22791
|
+
`;
|
|
22792
|
+
LIST_BEANS_TIMESTAMPS_QUERY = `
|
|
22793
|
+
query {
|
|
22794
|
+
beans { id updatedAt }
|
|
22795
|
+
}
|
|
22773
22796
|
`;
|
|
22774
22797
|
}
|
|
22775
22798
|
});
|
|
@@ -22792,12 +22815,26 @@ var init_backend = __esm({
|
|
|
22792
22815
|
init_graphql();
|
|
22793
22816
|
init_utils();
|
|
22794
22817
|
execFileAsync = (0, import_node_util.promisify)(import_node_child_process.execFile);
|
|
22795
|
-
BeansCliBackend = class {
|
|
22818
|
+
BeansCliBackend = class _BeansCliBackend {
|
|
22796
22819
|
constructor(workspaceRoot, cliPath, logDir) {
|
|
22797
22820
|
this.workspaceRoot = workspaceRoot;
|
|
22798
22821
|
this.cliPath = cliPath;
|
|
22799
22822
|
this.logDir = logDir;
|
|
22800
22823
|
}
|
|
22824
|
+
// ---------------------------------------------------------------------------
|
|
22825
|
+
// Cache
|
|
22826
|
+
// ---------------------------------------------------------------------------
|
|
22827
|
+
/** Full unfiltered records keyed by bean ID, stored under the fixed cache key `'all'`. */
|
|
22828
|
+
_cache = /* @__PURE__ */ new Map();
|
|
22829
|
+
/** Last time the unfiltered cache entry `'all'` was fetched (ms). */
|
|
22830
|
+
_cacheTime = /* @__PURE__ */ new Map();
|
|
22831
|
+
/** Short-circuit TTL: skip even the timestamp check within this window (ms). */
|
|
22832
|
+
static BURST_TTL_MS = 5e3;
|
|
22833
|
+
/** Invalidate the unfiltered list cache so the next call does a full fetch. */
|
|
22834
|
+
invalidateCache() {
|
|
22835
|
+
this._cache.delete("all");
|
|
22836
|
+
this._cacheTime.delete("all");
|
|
22837
|
+
}
|
|
22801
22838
|
/**
|
|
22802
22839
|
* Returns a safe environment for executing the Beans CLI,
|
|
22803
22840
|
* whitelisting only necessary variables.
|
|
@@ -22821,7 +22858,7 @@ var init_backend = __esm({
|
|
|
22821
22858
|
return (0, import_node_path2.resolve)(this.workspaceRoot, ".beans");
|
|
22822
22859
|
}
|
|
22823
22860
|
resolveBeanFilePath(relativePath) {
|
|
22824
|
-
const cleaned = relativePath.trim().replace(/^\/+/, "");
|
|
22861
|
+
const cleaned = relativePath.trim().replace(/^\/+/, "").replace(/^\.beans(?:[\\/]|$)/, "");
|
|
22825
22862
|
if (!cleaned) {
|
|
22826
22863
|
throw new Error("Path is required");
|
|
22827
22864
|
}
|
|
@@ -22879,10 +22916,48 @@ Output: ${stdout.slice(0, 1e3)}`
|
|
|
22879
22916
|
if (options?.search) {
|
|
22880
22917
|
filter.search = options.search;
|
|
22881
22918
|
}
|
|
22919
|
+
const isCacheable = !filter.status && !filter.type && !filter.search;
|
|
22920
|
+
const cacheKey = "all";
|
|
22921
|
+
if (isCacheable) {
|
|
22922
|
+
const lastFetch = this._cacheTime.get(cacheKey) ?? 0;
|
|
22923
|
+
const cached2 = this._cache.get(cacheKey);
|
|
22924
|
+
const age = Date.now() - lastFetch;
|
|
22925
|
+
if (cached2 && age < _BeansCliBackend.BURST_TTL_MS) {
|
|
22926
|
+
return Array.from(cached2.values());
|
|
22927
|
+
}
|
|
22928
|
+
if (cached2) {
|
|
22929
|
+
try {
|
|
22930
|
+
const { data: tsData } = await this.executeGraphQL(
|
|
22931
|
+
LIST_BEANS_TIMESTAMPS_QUERY
|
|
22932
|
+
);
|
|
22933
|
+
const timestamps = tsData.beans;
|
|
22934
|
+
let dirty = timestamps.length !== cached2.size;
|
|
22935
|
+
if (!dirty) {
|
|
22936
|
+
for (const { id, updatedAt } of timestamps) {
|
|
22937
|
+
const existing = cached2.get(id);
|
|
22938
|
+
if (!existing || existing.updatedAt !== updatedAt) {
|
|
22939
|
+
dirty = true;
|
|
22940
|
+
break;
|
|
22941
|
+
}
|
|
22942
|
+
}
|
|
22943
|
+
}
|
|
22944
|
+
if (!dirty) {
|
|
22945
|
+
this._cacheTime.set(cacheKey, Date.now());
|
|
22946
|
+
return Array.from(cached2.values());
|
|
22947
|
+
}
|
|
22948
|
+
} catch {
|
|
22949
|
+
}
|
|
22950
|
+
}
|
|
22951
|
+
}
|
|
22882
22952
|
const { data, errors } = await this.executeGraphQL(LIST_BEANS_QUERY, { filter });
|
|
22883
22953
|
if (errors && errors.length > 0) {
|
|
22884
22954
|
throw new Error(`GraphQL error: ${errors.map((e) => e.message).join(", ")}`);
|
|
22885
22955
|
}
|
|
22956
|
+
if (isCacheable) {
|
|
22957
|
+
const byId = new Map(data.beans.map((b) => [b.id, b]));
|
|
22958
|
+
this._cache.set(cacheKey, byId);
|
|
22959
|
+
this._cacheTime.set(cacheKey, Date.now());
|
|
22960
|
+
}
|
|
22886
22961
|
return data.beans;
|
|
22887
22962
|
}
|
|
22888
22963
|
async create(input) {
|
|
@@ -22891,7 +22966,7 @@ Output: ${stdout.slice(0, 1e3)}`
|
|
|
22891
22966
|
type: input.type,
|
|
22892
22967
|
status: input.status,
|
|
22893
22968
|
priority: input.priority,
|
|
22894
|
-
body: input.description,
|
|
22969
|
+
body: input.body ?? input.description,
|
|
22895
22970
|
parent: input.parent
|
|
22896
22971
|
};
|
|
22897
22972
|
const { data, errors } = await this.executeGraphQL(CREATE_BEAN_MUTATION, {
|
|
@@ -22900,6 +22975,7 @@ Output: ${stdout.slice(0, 1e3)}`
|
|
|
22900
22975
|
if (errors && errors.length > 0) {
|
|
22901
22976
|
throw new Error(`GraphQL error: ${errors.map((e) => e.message).join(", ")}`);
|
|
22902
22977
|
}
|
|
22978
|
+
this.invalidateCache();
|
|
22903
22979
|
return data.createBean;
|
|
22904
22980
|
}
|
|
22905
22981
|
async update(beanId, updates) {
|
|
@@ -22922,13 +22998,54 @@ Output: ${stdout.slice(0, 1e3)}`
|
|
|
22922
22998
|
if (updates.body !== void 0) {
|
|
22923
22999
|
updateInput.body = updates.body;
|
|
22924
23000
|
}
|
|
22925
|
-
const
|
|
22926
|
-
|
|
22927
|
-
|
|
22928
|
-
}
|
|
23001
|
+
const bodyMod = {};
|
|
23002
|
+
if (updates.bodyAppend !== void 0) {
|
|
23003
|
+
bodyMod.append = updates.bodyAppend;
|
|
23004
|
+
}
|
|
23005
|
+
if (Array.isArray(updates.bodyReplace) && updates.bodyReplace.length > 0) {
|
|
23006
|
+
bodyMod.replace = updates.bodyReplace;
|
|
23007
|
+
}
|
|
23008
|
+
if (Object.keys(bodyMod).length > 0) {
|
|
23009
|
+
updateInput.bodyMod = bodyMod;
|
|
23010
|
+
}
|
|
23011
|
+
let data;
|
|
23012
|
+
let errors;
|
|
23013
|
+
if (updates.ifMatch) {
|
|
23014
|
+
try {
|
|
23015
|
+
const res = await this.executeGraphQL(UPDATE_BEAN_MUTATION_WITH_IF_MATCH, {
|
|
23016
|
+
id: beanId,
|
|
23017
|
+
input: updateInput,
|
|
23018
|
+
ifMatch: updates.ifMatch
|
|
23019
|
+
});
|
|
23020
|
+
data = res.data;
|
|
23021
|
+
errors = res.errors;
|
|
23022
|
+
} catch (error48) {
|
|
23023
|
+
const message = error48.message || "";
|
|
23024
|
+
const unsupportedIfMatch = /unknown argument.*ifMatch|unknown field.*ifMatch|ifMatch.*not defined|field .*updateBean.* argument .*ifMatch/i.test(
|
|
23025
|
+
message
|
|
23026
|
+
);
|
|
23027
|
+
if (!unsupportedIfMatch) {
|
|
23028
|
+
throw error48;
|
|
23029
|
+
}
|
|
23030
|
+
const fallback = await this.executeGraphQL(UPDATE_BEAN_MUTATION, {
|
|
23031
|
+
id: beanId,
|
|
23032
|
+
input: updateInput
|
|
23033
|
+
});
|
|
23034
|
+
data = fallback.data;
|
|
23035
|
+
errors = fallback.errors;
|
|
23036
|
+
}
|
|
23037
|
+
} else {
|
|
23038
|
+
const res = await this.executeGraphQL(UPDATE_BEAN_MUTATION, {
|
|
23039
|
+
id: beanId,
|
|
23040
|
+
input: updateInput
|
|
23041
|
+
});
|
|
23042
|
+
data = res.data;
|
|
23043
|
+
errors = res.errors;
|
|
23044
|
+
}
|
|
22929
23045
|
if (errors && errors.length > 0) {
|
|
22930
23046
|
throw new Error(`GraphQL error: ${errors.map((e) => e.message).join(", ")}`);
|
|
22931
23047
|
}
|
|
23048
|
+
this.invalidateCache();
|
|
22932
23049
|
return data.updateBean;
|
|
22933
23050
|
}
|
|
22934
23051
|
async delete(beanId) {
|
|
@@ -22938,13 +23055,57 @@ Output: ${stdout.slice(0, 1e3)}`
|
|
|
22938
23055
|
if (errors && errors.length > 0) {
|
|
22939
23056
|
throw new Error(`GraphQL error: ${errors.map((e) => e.message).join(", ")}`);
|
|
22940
23057
|
}
|
|
23058
|
+
this.invalidateCache();
|
|
22941
23059
|
return { deleted: true, beanId };
|
|
22942
23060
|
}
|
|
23061
|
+
async bulkCreate(beans, defaultParent) {
|
|
23062
|
+
const results = [];
|
|
23063
|
+
for (const item of beans) {
|
|
23064
|
+
try {
|
|
23065
|
+
const bean = await this.create({
|
|
23066
|
+
...item,
|
|
23067
|
+
parent: item.parent ?? defaultParent
|
|
23068
|
+
});
|
|
23069
|
+
results.push({ bean });
|
|
23070
|
+
} catch (error48) {
|
|
23071
|
+
results.push({ error: error48.message });
|
|
23072
|
+
}
|
|
23073
|
+
}
|
|
23074
|
+
return results;
|
|
23075
|
+
}
|
|
23076
|
+
async bulkUpdate(beans, defaultParent) {
|
|
23077
|
+
const results = [];
|
|
23078
|
+
for (const { beanId, ...updates } of beans) {
|
|
23079
|
+
try {
|
|
23080
|
+
const resolvedParent = updates.parent ?? (updates.clearParent ? void 0 : defaultParent);
|
|
23081
|
+
const bean = await this.update(beanId, { ...updates, parent: resolvedParent });
|
|
23082
|
+
results.push({ beanId, bean });
|
|
23083
|
+
} catch (error48) {
|
|
23084
|
+
results.push({ beanId, error: error48.message });
|
|
23085
|
+
}
|
|
23086
|
+
}
|
|
23087
|
+
return results;
|
|
23088
|
+
}
|
|
22943
23089
|
async openConfig() {
|
|
22944
23090
|
const configPath = (0, import_node_path2.join)(this.workspaceRoot, ".beans.yml");
|
|
22945
23091
|
const content = await (0, import_promises.readFile)(configPath, "utf8");
|
|
22946
23092
|
return { configPath, content };
|
|
22947
23093
|
}
|
|
23094
|
+
async primeInstructions() {
|
|
23095
|
+
const { stdout } = await execFileAsync(this.cliPath, ["prime"], {
|
|
23096
|
+
cwd: this.workspaceRoot,
|
|
23097
|
+
env: this.getSafeEnv(),
|
|
23098
|
+
maxBuffer: 10 * 1024 * 1024,
|
|
23099
|
+
timeout: 3e4
|
|
23100
|
+
});
|
|
23101
|
+
return stdout.trim();
|
|
23102
|
+
}
|
|
23103
|
+
async writeInstructions(instructions) {
|
|
23104
|
+
const instructionsPath = (0, import_node_path2.join)(this.workspaceRoot, ".github", "instructions", "beans-prime.instructions.md");
|
|
23105
|
+
await (0, import_promises.mkdir)((0, import_node_path2.dirname)(instructionsPath), { recursive: true });
|
|
23106
|
+
await (0, import_promises.writeFile)(instructionsPath, instructions, "utf8");
|
|
23107
|
+
return instructionsPath;
|
|
23108
|
+
}
|
|
22948
23109
|
async graphqlSchema() {
|
|
22949
23110
|
const { stdout } = await execFileAsync(this.cliPath, ["graphql", "--schema"], {
|
|
22950
23111
|
cwd: this.workspaceRoot,
|
|
@@ -22983,6 +23144,120 @@ Output: ${stdout.slice(0, 1e3)}`
|
|
|
22983
23144
|
linesReturned: ringBuffer.length
|
|
22984
23145
|
};
|
|
22985
23146
|
}
|
|
23147
|
+
/**
|
|
23148
|
+
* Split a YAML scalar value from any trailing inline comment.
|
|
23149
|
+
* Understands single-quoted and double-quoted YAML strings so it won't
|
|
23150
|
+
* mistake a `#` inside a quoted value for a comment delimiter.
|
|
23151
|
+
*/
|
|
23152
|
+
splitYamlInlineComment(value) {
|
|
23153
|
+
let inSingle = false;
|
|
23154
|
+
let inDouble = false;
|
|
23155
|
+
for (let i = 0; i < value.length; i += 1) {
|
|
23156
|
+
const char = value[i];
|
|
23157
|
+
if (inSingle) {
|
|
23158
|
+
if (char === "'") {
|
|
23159
|
+
if (value[i + 1] === "'") {
|
|
23160
|
+
i += 1;
|
|
23161
|
+
} else {
|
|
23162
|
+
inSingle = false;
|
|
23163
|
+
}
|
|
23164
|
+
}
|
|
23165
|
+
continue;
|
|
23166
|
+
}
|
|
23167
|
+
if (inDouble) {
|
|
23168
|
+
if (char === "\\") {
|
|
23169
|
+
i += 1;
|
|
23170
|
+
continue;
|
|
23171
|
+
}
|
|
23172
|
+
if (char === '"') {
|
|
23173
|
+
inDouble = false;
|
|
23174
|
+
}
|
|
23175
|
+
continue;
|
|
23176
|
+
}
|
|
23177
|
+
if (char === "'") {
|
|
23178
|
+
inSingle = true;
|
|
23179
|
+
continue;
|
|
23180
|
+
}
|
|
23181
|
+
if (char === '"') {
|
|
23182
|
+
inDouble = true;
|
|
23183
|
+
continue;
|
|
23184
|
+
}
|
|
23185
|
+
if (char === "#" && i > 0 && /\s/.test(value[i - 1])) {
|
|
23186
|
+
const valuePart = value.slice(0, i).trimEnd();
|
|
23187
|
+
return {
|
|
23188
|
+
valuePart,
|
|
23189
|
+
commentPart: value.slice(valuePart.length)
|
|
23190
|
+
};
|
|
23191
|
+
}
|
|
23192
|
+
}
|
|
23193
|
+
return { valuePart: value, commentPart: "" };
|
|
23194
|
+
}
|
|
23195
|
+
/** Returns true when `value` looks like a YAML block scalar indicator (`>`, `|`, `>-`, `|-`, etc.) */
|
|
23196
|
+
isYamlBlockScalarIndicator(value) {
|
|
23197
|
+
return /^[>|][+-]?[0-9]*$/.test(value) || /^[>|][0-9]*[+-]?$/.test(value);
|
|
23198
|
+
}
|
|
23199
|
+
/** Escape a plain string for use inside a YAML double-quoted scalar. */
|
|
23200
|
+
escapeForYamlDoubleQuoted(value) {
|
|
23201
|
+
return value.replace(/\\/g, "\\\\").replace(/"/g, '\\"');
|
|
23202
|
+
}
|
|
23203
|
+
/**
|
|
23204
|
+
* Normalise a raw YAML title value to a double-quoted scalar.
|
|
23205
|
+
* Handles: empty, already double-quoted, single-quoted (unescaping `''`),
|
|
23206
|
+
* block-scalar indicators, and plain unquoted values.
|
|
23207
|
+
*/
|
|
23208
|
+
normalizeFrontmatterTitleValue(value) {
|
|
23209
|
+
const trimmed = value.trim();
|
|
23210
|
+
if (trimmed === "") {
|
|
23211
|
+
return '""';
|
|
23212
|
+
}
|
|
23213
|
+
if (this.isYamlBlockScalarIndicator(trimmed)) {
|
|
23214
|
+
return value;
|
|
23215
|
+
}
|
|
23216
|
+
if (/^"(?:[^"\\]|\\[\s\S])*"$/.test(trimmed)) {
|
|
23217
|
+
return trimmed;
|
|
23218
|
+
}
|
|
23219
|
+
if (/^'(?:[^']|'')*'$/.test(trimmed)) {
|
|
23220
|
+
const inner = trimmed.slice(1, -1).replace(/''/g, "'");
|
|
23221
|
+
return `"${this.escapeForYamlDoubleQuoted(inner)}"`;
|
|
23222
|
+
}
|
|
23223
|
+
return `"${this.escapeForYamlDoubleQuoted(trimmed)}"`;
|
|
23224
|
+
}
|
|
23225
|
+
/**
|
|
23226
|
+
* Ensure every `title:` line in YAML frontmatter is double-quoted.
|
|
23227
|
+
* Handles already-quoted (single or double), multi-word, and special-char values.
|
|
23228
|
+
* Preserves inline comments and handles both LF and CRLF line endings.
|
|
23229
|
+
*/
|
|
23230
|
+
quoteFrontmatterTitles(content) {
|
|
23231
|
+
const crlfOpen = content.startsWith("---\r\n");
|
|
23232
|
+
const lfOpen = content.startsWith("---\n");
|
|
23233
|
+
if (!crlfOpen && !lfOpen) {
|
|
23234
|
+
return content;
|
|
23235
|
+
}
|
|
23236
|
+
const eol = crlfOpen ? "\r\n" : "\n";
|
|
23237
|
+
const openEnd = `---${eol}`.length;
|
|
23238
|
+
const closeMarker = `${eol}---`;
|
|
23239
|
+
const closeIdx = content.indexOf(closeMarker, openEnd);
|
|
23240
|
+
if (closeIdx === -1) {
|
|
23241
|
+
return content;
|
|
23242
|
+
}
|
|
23243
|
+
const frontmatter = content.slice(openEnd, closeIdx);
|
|
23244
|
+
const rest = content.slice(closeIdx);
|
|
23245
|
+
const lines = frontmatter.split(eol);
|
|
23246
|
+
const fixedLines = lines.map((line) => {
|
|
23247
|
+
if (!line.startsWith("title:")) {
|
|
23248
|
+
return line;
|
|
23249
|
+
}
|
|
23250
|
+
const colonIdx = line.indexOf(":");
|
|
23251
|
+
const afterColon = line.slice(colonIdx + 1);
|
|
23252
|
+
const leadingSpace = afterColon.length - afterColon.trimStart().length;
|
|
23253
|
+
const raw = afterColon.trimStart();
|
|
23254
|
+
const { valuePart, commentPart } = this.splitYamlInlineComment(raw);
|
|
23255
|
+
const normalized = this.normalizeFrontmatterTitleValue(valuePart);
|
|
23256
|
+
const prefix = `title:${" ".repeat(Math.max(1, leadingSpace))}`;
|
|
23257
|
+
return `${prefix}${normalized}${commentPart}`;
|
|
23258
|
+
});
|
|
23259
|
+
return `---${eol}${fixedLines.join(eol)}${rest}`;
|
|
23260
|
+
}
|
|
22986
23261
|
async readBeanFile(relativePath) {
|
|
22987
23262
|
const absolutePath = this.resolveBeanFilePath(relativePath);
|
|
22988
23263
|
const content = await (0, import_promises.readFile)(absolutePath, "utf8");
|
|
@@ -22990,20 +23265,22 @@ Output: ${stdout.slice(0, 1e3)}`
|
|
|
22990
23265
|
}
|
|
22991
23266
|
async editBeanFile(relativePath, content) {
|
|
22992
23267
|
const absolutePath = this.resolveBeanFilePath(relativePath);
|
|
23268
|
+
const fixed = this.quoteFrontmatterTitles(content);
|
|
22993
23269
|
await (0, import_promises.mkdir)((0, import_node_path2.dirname)(absolutePath), { recursive: true });
|
|
22994
|
-
await (0, import_promises.writeFile)(absolutePath,
|
|
22995
|
-
return { path: absolutePath, bytes: Buffer.byteLength(
|
|
23270
|
+
await (0, import_promises.writeFile)(absolutePath, fixed, "utf8");
|
|
23271
|
+
return { path: absolutePath, bytes: Buffer.byteLength(fixed, "utf8") };
|
|
22996
23272
|
}
|
|
22997
23273
|
async createBeanFile(relativePath, content, options) {
|
|
22998
23274
|
const absolutePath = this.resolveBeanFilePath(relativePath);
|
|
23275
|
+
const fixed = this.quoteFrontmatterTitles(content);
|
|
22999
23276
|
await (0, import_promises.mkdir)((0, import_node_path2.dirname)(absolutePath), { recursive: true });
|
|
23000
|
-
await (0, import_promises.writeFile)(absolutePath,
|
|
23277
|
+
await (0, import_promises.writeFile)(absolutePath, fixed, {
|
|
23001
23278
|
encoding: "utf8",
|
|
23002
23279
|
flag: options?.overwrite ? "w" : "wx"
|
|
23003
23280
|
});
|
|
23004
23281
|
return {
|
|
23005
23282
|
path: absolutePath,
|
|
23006
|
-
bytes: Buffer.byteLength(
|
|
23283
|
+
bytes: Buffer.byteLength(fixed, "utf8"),
|
|
23007
23284
|
created: true
|
|
23008
23285
|
};
|
|
23009
23286
|
}
|
|
@@ -23016,7 +23293,7 @@ Output: ${stdout.slice(0, 1e3)}`
|
|
|
23016
23293
|
}
|
|
23017
23294
|
});
|
|
23018
23295
|
|
|
23019
|
-
// node_modules/.pnpm/@modelcontextprotocol+sdk@1.
|
|
23296
|
+
// node_modules/.pnpm/@modelcontextprotocol+sdk@1.29.0_zod@4.3.6/node_modules/@modelcontextprotocol/sdk/dist/esm/shared/stdio.js
|
|
23020
23297
|
function deserializeMessage(line) {
|
|
23021
23298
|
return JSONRPCMessageSchema.parse(JSON.parse(line));
|
|
23022
23299
|
}
|
|
@@ -23025,7 +23302,7 @@ function serializeMessage(message) {
|
|
|
23025
23302
|
}
|
|
23026
23303
|
var ReadBuffer;
|
|
23027
23304
|
var init_stdio = __esm({
|
|
23028
|
-
"node_modules/.pnpm/@modelcontextprotocol+sdk@1.
|
|
23305
|
+
"node_modules/.pnpm/@modelcontextprotocol+sdk@1.29.0_zod@4.3.6/node_modules/@modelcontextprotocol/sdk/dist/esm/shared/stdio.js"() {
|
|
23029
23306
|
"use strict";
|
|
23030
23307
|
init_types();
|
|
23031
23308
|
ReadBuffer = class {
|
|
@@ -23051,14 +23328,14 @@ var init_stdio = __esm({
|
|
|
23051
23328
|
}
|
|
23052
23329
|
});
|
|
23053
23330
|
|
|
23054
|
-
// node_modules/.pnpm/@modelcontextprotocol+sdk@1.
|
|
23331
|
+
// node_modules/.pnpm/@modelcontextprotocol+sdk@1.29.0_zod@4.3.6/node_modules/@modelcontextprotocol/sdk/dist/esm/server/stdio.js
|
|
23055
23332
|
var stdio_exports = {};
|
|
23056
23333
|
__export(stdio_exports, {
|
|
23057
23334
|
StdioServerTransport: () => StdioServerTransport
|
|
23058
23335
|
});
|
|
23059
23336
|
var import_node_process, StdioServerTransport;
|
|
23060
23337
|
var init_stdio2 = __esm({
|
|
23061
|
-
"node_modules/.pnpm/@modelcontextprotocol+sdk@1.
|
|
23338
|
+
"node_modules/.pnpm/@modelcontextprotocol+sdk@1.29.0_zod@4.3.6/node_modules/@modelcontextprotocol/sdk/dist/esm/server/stdio.js"() {
|
|
23062
23339
|
"use strict";
|
|
23063
23340
|
import_node_process = __toESM(require("process"), 1);
|
|
23064
23341
|
init_stdio();
|
|
@@ -27083,7 +27360,7 @@ init_core2();
|
|
|
27083
27360
|
// node_modules/.pnpm/zod@4.3.6/node_modules/zod/v4/mini/coerce.js
|
|
27084
27361
|
init_core2();
|
|
27085
27362
|
|
|
27086
|
-
// node_modules/.pnpm/@modelcontextprotocol+sdk@1.
|
|
27363
|
+
// node_modules/.pnpm/@modelcontextprotocol+sdk@1.29.0_zod@4.3.6/node_modules/@modelcontextprotocol/sdk/dist/esm/server/zod-compat.js
|
|
27087
27364
|
function isZ4Schema(s) {
|
|
27088
27365
|
const schema = s;
|
|
27089
27366
|
return !!schema._zod;
|
|
@@ -27227,10 +27504,10 @@ function getLiteralValue(schema) {
|
|
|
27227
27504
|
return void 0;
|
|
27228
27505
|
}
|
|
27229
27506
|
|
|
27230
|
-
// node_modules/.pnpm/@modelcontextprotocol+sdk@1.
|
|
27507
|
+
// node_modules/.pnpm/@modelcontextprotocol+sdk@1.29.0_zod@4.3.6/node_modules/@modelcontextprotocol/sdk/dist/esm/shared/protocol.js
|
|
27231
27508
|
init_types();
|
|
27232
27509
|
|
|
27233
|
-
// node_modules/.pnpm/@modelcontextprotocol+sdk@1.
|
|
27510
|
+
// node_modules/.pnpm/@modelcontextprotocol+sdk@1.29.0_zod@4.3.6/node_modules/@modelcontextprotocol/sdk/dist/esm/experimental/tasks/interfaces.js
|
|
27234
27511
|
function isTerminal(status) {
|
|
27235
27512
|
return status === "completed" || status === "failed" || status === "cancelled";
|
|
27236
27513
|
}
|
|
@@ -28519,7 +28796,7 @@ var zodToJsonSchema = (schema, options) => {
|
|
|
28519
28796
|
return combined;
|
|
28520
28797
|
};
|
|
28521
28798
|
|
|
28522
|
-
// node_modules/.pnpm/@modelcontextprotocol+sdk@1.
|
|
28799
|
+
// node_modules/.pnpm/@modelcontextprotocol+sdk@1.29.0_zod@4.3.6/node_modules/@modelcontextprotocol/sdk/dist/esm/server/zod-json-schema-compat.js
|
|
28523
28800
|
function mapMiniTarget(t) {
|
|
28524
28801
|
if (!t)
|
|
28525
28802
|
return "draft-7";
|
|
@@ -28561,7 +28838,7 @@ function parseWithCompat(schema, data) {
|
|
|
28561
28838
|
return result.data;
|
|
28562
28839
|
}
|
|
28563
28840
|
|
|
28564
|
-
// node_modules/.pnpm/@modelcontextprotocol+sdk@1.
|
|
28841
|
+
// node_modules/.pnpm/@modelcontextprotocol+sdk@1.29.0_zod@4.3.6/node_modules/@modelcontextprotocol/sdk/dist/esm/shared/protocol.js
|
|
28565
28842
|
var DEFAULT_REQUEST_TIMEOUT_MSEC = 6e4;
|
|
28566
28843
|
var Protocol = class {
|
|
28567
28844
|
constructor(_options) {
|
|
@@ -28773,6 +29050,10 @@ var Protocol = class {
|
|
|
28773
29050
|
this._progressHandlers.clear();
|
|
28774
29051
|
this._taskProgressTokens.clear();
|
|
28775
29052
|
this._pendingDebouncedNotifications.clear();
|
|
29053
|
+
for (const info of this._timeoutInfo.values()) {
|
|
29054
|
+
clearTimeout(info.timeoutId);
|
|
29055
|
+
}
|
|
29056
|
+
this._timeoutInfo.clear();
|
|
28776
29057
|
for (const controller of this._requestHandlerAbortControllers.values()) {
|
|
28777
29058
|
controller.abort();
|
|
28778
29059
|
}
|
|
@@ -28903,7 +29184,9 @@ var Protocol = class {
|
|
|
28903
29184
|
await capturedTransport?.send(errorResponse);
|
|
28904
29185
|
}
|
|
28905
29186
|
}).catch((error48) => this._onerror(new Error(`Failed to send response: ${error48}`))).finally(() => {
|
|
28906
|
-
this._requestHandlerAbortControllers.
|
|
29187
|
+
if (this._requestHandlerAbortControllers.get(request.id) === abortController) {
|
|
29188
|
+
this._requestHandlerAbortControllers.delete(request.id);
|
|
29189
|
+
}
|
|
28907
29190
|
});
|
|
28908
29191
|
}
|
|
28909
29192
|
_onprogress(notification) {
|
|
@@ -29509,10 +29792,10 @@ function mergeCapabilities(base, additional) {
|
|
|
29509
29792
|
return result;
|
|
29510
29793
|
}
|
|
29511
29794
|
|
|
29512
|
-
// node_modules/.pnpm/@modelcontextprotocol+sdk@1.
|
|
29795
|
+
// node_modules/.pnpm/@modelcontextprotocol+sdk@1.29.0_zod@4.3.6/node_modules/@modelcontextprotocol/sdk/dist/esm/server/index.js
|
|
29513
29796
|
init_types();
|
|
29514
29797
|
|
|
29515
|
-
// node_modules/.pnpm/@modelcontextprotocol+sdk@1.
|
|
29798
|
+
// node_modules/.pnpm/@modelcontextprotocol+sdk@1.29.0_zod@4.3.6/node_modules/@modelcontextprotocol/sdk/dist/esm/validation/ajv-provider.js
|
|
29516
29799
|
var import_ajv = __toESM(require_ajv(), 1);
|
|
29517
29800
|
var import_ajv_formats = __toESM(require_dist(), 1);
|
|
29518
29801
|
function createDefaultAjvInstance() {
|
|
@@ -29580,7 +29863,7 @@ var AjvJsonSchemaValidator = class {
|
|
|
29580
29863
|
}
|
|
29581
29864
|
};
|
|
29582
29865
|
|
|
29583
|
-
// node_modules/.pnpm/@modelcontextprotocol+sdk@1.
|
|
29866
|
+
// node_modules/.pnpm/@modelcontextprotocol+sdk@1.29.0_zod@4.3.6/node_modules/@modelcontextprotocol/sdk/dist/esm/experimental/tasks/server.js
|
|
29584
29867
|
init_types();
|
|
29585
29868
|
var ExperimentalServerTasks = class {
|
|
29586
29869
|
constructor(_server) {
|
|
@@ -29794,7 +30077,7 @@ var ExperimentalServerTasks = class {
|
|
|
29794
30077
|
}
|
|
29795
30078
|
};
|
|
29796
30079
|
|
|
29797
|
-
// node_modules/.pnpm/@modelcontextprotocol+sdk@1.
|
|
30080
|
+
// node_modules/.pnpm/@modelcontextprotocol+sdk@1.29.0_zod@4.3.6/node_modules/@modelcontextprotocol/sdk/dist/esm/experimental/tasks/helpers.js
|
|
29798
30081
|
function assertToolsCallTaskCapability(requests, method, entityName) {
|
|
29799
30082
|
if (!requests) {
|
|
29800
30083
|
throw new Error(`${entityName} does not support task creation (required for ${method})`);
|
|
@@ -29829,7 +30112,7 @@ function assertClientRequestTaskCapability(requests, method, entityName) {
|
|
|
29829
30112
|
}
|
|
29830
30113
|
}
|
|
29831
30114
|
|
|
29832
|
-
// node_modules/.pnpm/@modelcontextprotocol+sdk@1.
|
|
30115
|
+
// node_modules/.pnpm/@modelcontextprotocol+sdk@1.29.0_zod@4.3.6/node_modules/@modelcontextprotocol/sdk/dist/esm/server/index.js
|
|
29833
30116
|
var Server = class extends Protocol {
|
|
29834
30117
|
/**
|
|
29835
30118
|
* Initializes this server with the given name and version information.
|
|
@@ -30209,10 +30492,10 @@ var Server = class extends Protocol {
|
|
|
30209
30492
|
}
|
|
30210
30493
|
};
|
|
30211
30494
|
|
|
30212
|
-
// node_modules/.pnpm/@modelcontextprotocol+sdk@1.
|
|
30495
|
+
// node_modules/.pnpm/@modelcontextprotocol+sdk@1.29.0_zod@4.3.6/node_modules/@modelcontextprotocol/sdk/dist/esm/server/mcp.js
|
|
30213
30496
|
init_types();
|
|
30214
30497
|
|
|
30215
|
-
// node_modules/.pnpm/@modelcontextprotocol+sdk@1.
|
|
30498
|
+
// node_modules/.pnpm/@modelcontextprotocol+sdk@1.29.0_zod@4.3.6/node_modules/@modelcontextprotocol/sdk/dist/esm/server/completable.js
|
|
30216
30499
|
var COMPLETABLE_SYMBOL = /* @__PURE__ */ Symbol.for("mcp.completable");
|
|
30217
30500
|
function isCompletable(schema) {
|
|
30218
30501
|
return !!schema && typeof schema === "object" && COMPLETABLE_SYMBOL in schema;
|
|
@@ -30226,7 +30509,7 @@ var McpZodTypeKind;
|
|
|
30226
30509
|
McpZodTypeKind2["Completable"] = "McpCompletable";
|
|
30227
30510
|
})(McpZodTypeKind || (McpZodTypeKind = {}));
|
|
30228
30511
|
|
|
30229
|
-
// node_modules/.pnpm/@modelcontextprotocol+sdk@1.
|
|
30512
|
+
// node_modules/.pnpm/@modelcontextprotocol+sdk@1.29.0_zod@4.3.6/node_modules/@modelcontextprotocol/sdk/dist/esm/shared/toolNameValidation.js
|
|
30230
30513
|
var TOOL_NAME_REGEX = /^[A-Za-z0-9._-]{1,128}$/;
|
|
30231
30514
|
function validateToolName(name) {
|
|
30232
30515
|
const warnings = [];
|
|
@@ -30284,7 +30567,7 @@ function validateAndWarnToolName(name) {
|
|
|
30284
30567
|
return result.isValid;
|
|
30285
30568
|
}
|
|
30286
30569
|
|
|
30287
|
-
// node_modules/.pnpm/@modelcontextprotocol+sdk@1.
|
|
30570
|
+
// node_modules/.pnpm/@modelcontextprotocol+sdk@1.29.0_zod@4.3.6/node_modules/@modelcontextprotocol/sdk/dist/esm/experimental/tasks/mcp-server.js
|
|
30288
30571
|
var ExperimentalMcpServerTasks = class {
|
|
30289
30572
|
constructor(_mcpServer) {
|
|
30290
30573
|
this._mcpServer = _mcpServer;
|
|
@@ -30303,7 +30586,7 @@ var ExperimentalMcpServerTasks = class {
|
|
|
30303
30586
|
init_external();
|
|
30304
30587
|
init_external();
|
|
30305
30588
|
|
|
30306
|
-
// node_modules/.pnpm/@modelcontextprotocol+sdk@1.
|
|
30589
|
+
// node_modules/.pnpm/@modelcontextprotocol+sdk@1.29.0_zod@4.3.6/node_modules/@modelcontextprotocol/sdk/dist/esm/server/mcp.js
|
|
30307
30590
|
var McpServer = class {
|
|
30308
30591
|
constructor(serverInfo, options) {
|
|
30309
30592
|
this._registeredResources = {};
|
|
@@ -30927,6 +31210,9 @@ var McpServer = class {
|
|
|
30927
31210
|
annotations = rest.shift();
|
|
30928
31211
|
}
|
|
30929
31212
|
} else if (typeof firstArg === "object" && firstArg !== null) {
|
|
31213
|
+
if (Object.values(firstArg).some((v) => typeof v === "object" && v !== null)) {
|
|
31214
|
+
throw new Error(`Tool ${name} expected a Zod schema or ToolAnnotations, but received an unrecognized object`);
|
|
31215
|
+
}
|
|
30930
31216
|
annotations = rest.shift();
|
|
30931
31217
|
}
|
|
30932
31218
|
}
|
|
@@ -31045,6 +31331,9 @@ function getZodSchemaObject(schema) {
|
|
|
31045
31331
|
if (isZodRawShapeCompat(schema)) {
|
|
31046
31332
|
return objectFromShape(schema);
|
|
31047
31333
|
}
|
|
31334
|
+
if (!isZodSchemaInstance(schema)) {
|
|
31335
|
+
throw new Error("inputSchema must be a Zod schema or raw shape, received an unrecognized object");
|
|
31336
|
+
}
|
|
31048
31337
|
return schema;
|
|
31049
31338
|
}
|
|
31050
31339
|
function promptArgumentsFromSchema(schema) {
|
|
@@ -31089,6 +31378,94 @@ var EMPTY_COMPLETION_RESULT = {
|
|
|
31089
31378
|
}
|
|
31090
31379
|
};
|
|
31091
31380
|
|
|
31381
|
+
// src/server/BeansMcpServer.ts
|
|
31382
|
+
var import_node_child_process2 = require("child_process");
|
|
31383
|
+
var import_node_util2 = require("util");
|
|
31384
|
+
|
|
31385
|
+
// package.json
|
|
31386
|
+
var package_default = {
|
|
31387
|
+
name: "@selfagency/beans-mcp",
|
|
31388
|
+
version: "0.5.0",
|
|
31389
|
+
private: false,
|
|
31390
|
+
description: "MCP (Model Context Protocol) server for Beans issue tracker",
|
|
31391
|
+
author: {
|
|
31392
|
+
name: "Daniel Sieradski",
|
|
31393
|
+
email: "daniel@self.agency",
|
|
31394
|
+
url: "https://self.agency"
|
|
31395
|
+
},
|
|
31396
|
+
homepage: "https://github.com/selfagency/beans-mcp",
|
|
31397
|
+
bugs: {
|
|
31398
|
+
url: "https://github.com/selfagency/beans-mcp/issues"
|
|
31399
|
+
},
|
|
31400
|
+
repository: {
|
|
31401
|
+
type: "git",
|
|
31402
|
+
url: "git+https://github.com/selfagency/beans-mcp.git"
|
|
31403
|
+
},
|
|
31404
|
+
mcpName: "io.github.selfagency/beans-mcp",
|
|
31405
|
+
keywords: [
|
|
31406
|
+
"beans",
|
|
31407
|
+
"mcp",
|
|
31408
|
+
"model-context-protocol",
|
|
31409
|
+
"issue-tracker",
|
|
31410
|
+
"ai"
|
|
31411
|
+
],
|
|
31412
|
+
license: "MIT",
|
|
31413
|
+
type: "module",
|
|
31414
|
+
exports: {
|
|
31415
|
+
".": {
|
|
31416
|
+
types: "./dist/index.d.ts",
|
|
31417
|
+
import: "./dist/index.js",
|
|
31418
|
+
require: "./dist/index.cjs"
|
|
31419
|
+
}
|
|
31420
|
+
},
|
|
31421
|
+
main: "./dist/index.cjs",
|
|
31422
|
+
module: "./dist/index.js",
|
|
31423
|
+
types: "./dist/index.d.ts",
|
|
31424
|
+
bin: {
|
|
31425
|
+
"beans-mcp": "dist/beans-mcp-server.cjs"
|
|
31426
|
+
},
|
|
31427
|
+
scripts: {
|
|
31428
|
+
build: "tsup",
|
|
31429
|
+
format: "oxfmt",
|
|
31430
|
+
"lint:fix": "oxlint --fix",
|
|
31431
|
+
lint: "oxlint",
|
|
31432
|
+
postbuild: "node ./scripts/write-dist-package.js",
|
|
31433
|
+
prepare: "husky",
|
|
31434
|
+
release: "zx ./scripts/release.js",
|
|
31435
|
+
"test:coverage": "vitest run --coverage",
|
|
31436
|
+
"test:watch": "vitest",
|
|
31437
|
+
test: "vitest run",
|
|
31438
|
+
"type-check": "tsc --noEmit"
|
|
31439
|
+
},
|
|
31440
|
+
devDependencies: {
|
|
31441
|
+
"@modelcontextprotocol/sdk": "^1.29.0",
|
|
31442
|
+
"@octokit/rest": "^22.0.1",
|
|
31443
|
+
"@types/node": "25.5.2",
|
|
31444
|
+
"@vitest/coverage-v8": "^4.1.2",
|
|
31445
|
+
"@vitest/ui": "4.1.2",
|
|
31446
|
+
husky: "^9.1.7",
|
|
31447
|
+
"lint-staged": "^16.4.0",
|
|
31448
|
+
ora: "^9.3.0",
|
|
31449
|
+
oxfmt: "^0.43.0",
|
|
31450
|
+
oxlint: "^1.58.0",
|
|
31451
|
+
"oxlint-tsgolint": "^0.20.0",
|
|
31452
|
+
tsup: "8.5.1",
|
|
31453
|
+
typescript: "6.0.2",
|
|
31454
|
+
vitest: "4.1.2",
|
|
31455
|
+
zod: "4.3.6",
|
|
31456
|
+
zx: "^8.8.5"
|
|
31457
|
+
},
|
|
31458
|
+
engines: {
|
|
31459
|
+
node: ">=18"
|
|
31460
|
+
},
|
|
31461
|
+
"lint-staged": {
|
|
31462
|
+
"src/**/*.ts": [
|
|
31463
|
+
"pnpm run lint:fix",
|
|
31464
|
+
"pnpm run format"
|
|
31465
|
+
]
|
|
31466
|
+
}
|
|
31467
|
+
};
|
|
31468
|
+
|
|
31092
31469
|
// src/internal/queryHelpers.ts
|
|
31093
31470
|
function sortBeansInternal(beans, mode) {
|
|
31094
31471
|
const sorted = [...beans];
|
|
@@ -31144,15 +31521,23 @@ async function handleQueryOperation(backend, params) {
|
|
|
31144
31521
|
const { operation, mode, statuses, types, search, tags, writeToWorkspaceInstructions, includeClosed } = params;
|
|
31145
31522
|
if (operation === "llm_context") {
|
|
31146
31523
|
const graphqlSchema = typeof backend.graphqlSchema === "function" ? await backend.graphqlSchema() : "";
|
|
31147
|
-
|
|
31524
|
+
let generatedInstructions = "";
|
|
31525
|
+
if (typeof backend.primeInstructions === "function") {
|
|
31526
|
+
try {
|
|
31527
|
+
generatedInstructions = await backend.primeInstructions();
|
|
31528
|
+
} catch {
|
|
31529
|
+
generatedInstructions = "";
|
|
31530
|
+
}
|
|
31531
|
+
}
|
|
31532
|
+
const instructionsPath = writeToWorkspaceInstructions && typeof backend.writeInstructions === "function" ? await backend.writeInstructions(generatedInstructions) : null;
|
|
31148
31533
|
return {
|
|
31149
31534
|
content: [
|
|
31150
31535
|
{
|
|
31151
31536
|
type: "text",
|
|
31152
|
-
text: JSON.stringify({ graphqlSchema, generatedInstructions
|
|
31537
|
+
text: JSON.stringify({ graphqlSchema, generatedInstructions, instructionsPath }, null, 2)
|
|
31153
31538
|
}
|
|
31154
31539
|
],
|
|
31155
|
-
structuredContent: { graphqlSchema, generatedInstructions
|
|
31540
|
+
structuredContent: { graphqlSchema, generatedInstructions, instructionsPath }
|
|
31156
31541
|
};
|
|
31157
31542
|
}
|
|
31158
31543
|
if (operation === "open_config") {
|
|
@@ -31198,6 +31583,31 @@ async function handleQueryOperation(backend, params) {
|
|
|
31198
31583
|
structuredContent: { query: search, count: beans2.length, beans: beans2 }
|
|
31199
31584
|
};
|
|
31200
31585
|
}
|
|
31586
|
+
if (operation === "ready") {
|
|
31587
|
+
const allBeans = await backend.list();
|
|
31588
|
+
const byId = new Map(allBeans.map((bean) => [bean.id, bean]));
|
|
31589
|
+
const candidates = await backend.list({ status: normalizedStatuses, type: normalizedTypes, search });
|
|
31590
|
+
const readyBeans = candidates.filter((bean) => {
|
|
31591
|
+
if (bean.status !== "todo") {
|
|
31592
|
+
return false;
|
|
31593
|
+
}
|
|
31594
|
+
const blockedBy = bean.blockedByIds || [];
|
|
31595
|
+
if (blockedBy.length === 0) {
|
|
31596
|
+
return true;
|
|
31597
|
+
}
|
|
31598
|
+
return blockedBy.every((blockerId) => {
|
|
31599
|
+
const blocker = byId.get(blockerId);
|
|
31600
|
+
if (!blocker) {
|
|
31601
|
+
return false;
|
|
31602
|
+
}
|
|
31603
|
+
return blocker.status === "completed" || blocker.status === "scrapped";
|
|
31604
|
+
});
|
|
31605
|
+
});
|
|
31606
|
+
return {
|
|
31607
|
+
content: [{ type: "text", text: JSON.stringify({ count: readyBeans.length, beans: readyBeans }, null, 2) }],
|
|
31608
|
+
structuredContent: { count: readyBeans.length, beans: readyBeans }
|
|
31609
|
+
};
|
|
31610
|
+
}
|
|
31201
31611
|
const beans = await backend.list({ status: normalizedStatuses, type: normalizedTypes, search });
|
|
31202
31612
|
const sorted = sortBeansInternal(beans, mode ?? "status-priority-type-title");
|
|
31203
31613
|
return {
|
|
@@ -31216,92 +31626,45 @@ var MAX_PATH_LENGTH = 1024;
|
|
|
31216
31626
|
|
|
31217
31627
|
// src/server/BeansMcpServer.ts
|
|
31218
31628
|
init_utils();
|
|
31219
|
-
|
|
31220
|
-
|
|
31221
|
-
|
|
31222
|
-
|
|
31223
|
-
|
|
31224
|
-
|
|
31225
|
-
|
|
31226
|
-
|
|
31227
|
-
name: "Daniel Sieradski",
|
|
31228
|
-
email: "daniel@self.agency",
|
|
31229
|
-
url: "https://self.agency"
|
|
31230
|
-
},
|
|
31231
|
-
homepage: "https://github.com/hmans/beans",
|
|
31232
|
-
bugs: {
|
|
31233
|
-
url: "https://github.com/selfagency/beans-mcp/issues"
|
|
31234
|
-
},
|
|
31235
|
-
repository: {
|
|
31236
|
-
type: "git",
|
|
31237
|
-
url: "git+https://github.com/selfagency/beans-mcp.git"
|
|
31238
|
-
},
|
|
31239
|
-
mcpName: "io.github.selfagency/beans-mcp",
|
|
31240
|
-
keywords: [
|
|
31241
|
-
"beans",
|
|
31242
|
-
"mcp",
|
|
31243
|
-
"model-context-protocol",
|
|
31244
|
-
"issue-tracker",
|
|
31245
|
-
"ai"
|
|
31246
|
-
],
|
|
31247
|
-
license: "MIT",
|
|
31248
|
-
type: "module",
|
|
31249
|
-
exports: {
|
|
31250
|
-
".": {
|
|
31251
|
-
types: "./dist/index.d.ts",
|
|
31252
|
-
import: "./dist/index.js",
|
|
31253
|
-
require: "./dist/index.cjs"
|
|
31629
|
+
var execFileAsync2 = (0, import_node_util2.promisify)(import_node_child_process2.execFile);
|
|
31630
|
+
var PACKAGE_VERSION = package_default.version ?? "0.0.0-dev";
|
|
31631
|
+
function getSafeCliEnv(env) {
|
|
31632
|
+
const whitelist = ["PATH", "HOME", "USER", "LANG", "LC_ALL", "LC_CTYPE", "SHELL"];
|
|
31633
|
+
const safeEnv = {};
|
|
31634
|
+
for (const key of whitelist) {
|
|
31635
|
+
if (env[key]) {
|
|
31636
|
+
safeEnv[key] = env[key];
|
|
31254
31637
|
}
|
|
31255
|
-
},
|
|
31256
|
-
main: "./dist/index.cjs",
|
|
31257
|
-
module: "./dist/index.js",
|
|
31258
|
-
types: "./dist/index.d.ts",
|
|
31259
|
-
bin: {
|
|
31260
|
-
"beans-mcp": "dist/beans-mcp-server.cjs"
|
|
31261
|
-
},
|
|
31262
|
-
scripts: {
|
|
31263
|
-
build: "tsup",
|
|
31264
|
-
format: "oxfmt",
|
|
31265
|
-
"lint:fix": "oxlint --fix",
|
|
31266
|
-
lint: "oxlint",
|
|
31267
|
-
postbuild: "node ./scripts/write-dist-package.js",
|
|
31268
|
-
prepare: "husky",
|
|
31269
|
-
release: "zx ./scripts/release.js",
|
|
31270
|
-
"test:coverage": "vitest run --coverage",
|
|
31271
|
-
"test:watch": "vitest",
|
|
31272
|
-
test: "vitest run",
|
|
31273
|
-
"type-check": "tsc --noEmit"
|
|
31274
|
-
},
|
|
31275
|
-
devDependencies: {
|
|
31276
|
-
"@modelcontextprotocol/sdk": "^1.27.1",
|
|
31277
|
-
"@octokit/rest": "^22.0.1",
|
|
31278
|
-
"@types/node": "^20.19.0",
|
|
31279
|
-
"@vitest/coverage-v8": "^4.0.18",
|
|
31280
|
-
"@vitest/ui": "4.0.18",
|
|
31281
|
-
husky: "^9.1.7",
|
|
31282
|
-
"lint-staged": "^16.2.7",
|
|
31283
|
-
ora: "^9.3.0",
|
|
31284
|
-
oxfmt: "^0.35.0",
|
|
31285
|
-
oxlint: "^1.50.0",
|
|
31286
|
-
"oxlint-tsgolint": "^0.15.0",
|
|
31287
|
-
tsup: "8.5.1",
|
|
31288
|
-
typescript: "^5.9.3",
|
|
31289
|
-
vitest: "4.0.18",
|
|
31290
|
-
zod: "4.3.6",
|
|
31291
|
-
zx: "^8.8.5"
|
|
31292
|
-
},
|
|
31293
|
-
engines: {
|
|
31294
|
-
node: ">=18"
|
|
31295
|
-
},
|
|
31296
|
-
"lint-staged": {
|
|
31297
|
-
"src/**/*.ts": [
|
|
31298
|
-
"pnpm run lint:fix",
|
|
31299
|
-
"pnpm run format"
|
|
31300
|
-
]
|
|
31301
31638
|
}
|
|
31302
|
-
|
|
31303
|
-
|
|
31304
|
-
|
|
31639
|
+
for (const key in env) {
|
|
31640
|
+
if (key.startsWith("BEANS_")) {
|
|
31641
|
+
safeEnv[key] = env[key];
|
|
31642
|
+
}
|
|
31643
|
+
}
|
|
31644
|
+
return safeEnv;
|
|
31645
|
+
}
|
|
31646
|
+
function extractVersionFromOutput(output) {
|
|
31647
|
+
const trimmed = output.trim();
|
|
31648
|
+
if (!trimmed) {
|
|
31649
|
+
return null;
|
|
31650
|
+
}
|
|
31651
|
+
const match = trimmed.match(/(?:^|[^\d])v?(\d+\.\d+\.\d+(?:[-+][0-9A-Za-z.-]+)?)/);
|
|
31652
|
+
return match?.[1] ?? null;
|
|
31653
|
+
}
|
|
31654
|
+
async function detectBeansCliVersion(cliPath, workspaceRoot) {
|
|
31655
|
+
try {
|
|
31656
|
+
const { stdout, stderr } = await execFileAsync2(cliPath, ["version"], {
|
|
31657
|
+
cwd: workspaceRoot,
|
|
31658
|
+
env: getSafeCliEnv(process.env),
|
|
31659
|
+
maxBuffer: 1024 * 1024,
|
|
31660
|
+
timeout: 5e3
|
|
31661
|
+
});
|
|
31662
|
+
return extractVersionFromOutput(`${stdout}
|
|
31663
|
+
${stderr}`);
|
|
31664
|
+
} catch {
|
|
31665
|
+
return null;
|
|
31666
|
+
}
|
|
31667
|
+
}
|
|
31305
31668
|
async function getBeanById(backend, beanId) {
|
|
31306
31669
|
try {
|
|
31307
31670
|
const beans = await backend.list();
|
|
@@ -31321,7 +31684,40 @@ function initHandler(backend) {
|
|
|
31321
31684
|
};
|
|
31322
31685
|
}
|
|
31323
31686
|
function viewHandler(backend) {
|
|
31324
|
-
return async ({ beanId }) =>
|
|
31687
|
+
return async ({ beanId, beanIds }) => {
|
|
31688
|
+
const ids = Array.isArray(beanIds) && beanIds.length > 0 ? beanIds : beanId ? [beanId] : [];
|
|
31689
|
+
if (ids.length === 0) {
|
|
31690
|
+
throw new Error("Either beanId or beanIds must be provided");
|
|
31691
|
+
}
|
|
31692
|
+
if (ids.length === 1) {
|
|
31693
|
+
const bean = await getBeanById(backend, ids[0]);
|
|
31694
|
+
return makeTextAndStructured({ bean });
|
|
31695
|
+
}
|
|
31696
|
+
const beans = await backend.list();
|
|
31697
|
+
const byId = new Map(beans.map((b) => [b.id, b]));
|
|
31698
|
+
const found = ids.map((id) => byId.get(id)).filter(Boolean);
|
|
31699
|
+
const missingBeanIds = ids.filter((id) => !byId.has(id));
|
|
31700
|
+
return makeTextAndStructured({
|
|
31701
|
+
beans: found,
|
|
31702
|
+
missingBeanIds,
|
|
31703
|
+
count: found.length,
|
|
31704
|
+
requestedCount: ids.length
|
|
31705
|
+
});
|
|
31706
|
+
};
|
|
31707
|
+
}
|
|
31708
|
+
async function checkVersionCompatibility(cliPath, workspaceRoot, detector) {
|
|
31709
|
+
const detectedBeansVersion = await detector(cliPath, workspaceRoot);
|
|
31710
|
+
if (!detectedBeansVersion) {
|
|
31711
|
+
console.error(
|
|
31712
|
+
`[beans-mcp] warning: unable to determine Beans CLI version from \`${cliPath}\`; proceeding without version compatibility checks.`
|
|
31713
|
+
);
|
|
31714
|
+
return;
|
|
31715
|
+
}
|
|
31716
|
+
if (detectedBeansVersion !== PACKAGE_VERSION) {
|
|
31717
|
+
console.error(
|
|
31718
|
+
`[beans-mcp] warning: version mismatch detected (beans=${detectedBeansVersion}, beans-mcp=${PACKAGE_VERSION}); continuing startup.`
|
|
31719
|
+
);
|
|
31720
|
+
}
|
|
31325
31721
|
}
|
|
31326
31722
|
function createHandler(backend) {
|
|
31327
31723
|
return async (input) => makeTextAndStructured({ bean: await backend.create(input) });
|
|
@@ -31357,17 +31753,82 @@ function updateHandler(backend) {
|
|
|
31357
31753
|
clearParent: input.clearParent,
|
|
31358
31754
|
blocking: input.blocking,
|
|
31359
31755
|
blockedBy: input.blockedBy,
|
|
31360
|
-
body: input.body
|
|
31756
|
+
body: input.body,
|
|
31757
|
+
bodyAppend: input.bodyAppend,
|
|
31758
|
+
bodyReplace: input.bodyReplace,
|
|
31759
|
+
ifMatch: input.ifMatch
|
|
31361
31760
|
})
|
|
31362
31761
|
});
|
|
31363
31762
|
}
|
|
31364
31763
|
function deleteHandler(backend) {
|
|
31365
|
-
return async ({ beanId, force }) => {
|
|
31366
|
-
const
|
|
31367
|
-
if (
|
|
31368
|
-
throw new Error("
|
|
31764
|
+
return async ({ beanId, beanIds, force }) => {
|
|
31765
|
+
const ids = Array.isArray(beanIds) && beanIds.length > 0 ? beanIds : beanId ? [beanId] : [];
|
|
31766
|
+
if (ids.length === 0) {
|
|
31767
|
+
throw new Error("Either beanId or beanIds must be provided");
|
|
31369
31768
|
}
|
|
31370
|
-
|
|
31769
|
+
if (ids.length === 1) {
|
|
31770
|
+
const bean = await getBeanById(backend, ids[0]);
|
|
31771
|
+
if (!force && bean.status !== "draft" && bean.status !== "scrapped") {
|
|
31772
|
+
throw new Error("Only draft and scrapped beans are deletable unless force=true");
|
|
31773
|
+
}
|
|
31774
|
+
return makeTextAndStructured(await backend.delete(ids[0]));
|
|
31775
|
+
}
|
|
31776
|
+
const beans = await backend.list();
|
|
31777
|
+
const byId = new Map(beans.map((b) => [b.id, b]));
|
|
31778
|
+
const results = [];
|
|
31779
|
+
for (const id of ids) {
|
|
31780
|
+
const bean = byId.get(id);
|
|
31781
|
+
if (!bean) {
|
|
31782
|
+
results.push({ beanId: id, deleted: false, error: "Bean not found" });
|
|
31783
|
+
continue;
|
|
31784
|
+
}
|
|
31785
|
+
if (!force && bean.status !== "draft" && bean.status !== "scrapped") {
|
|
31786
|
+
results.push({
|
|
31787
|
+
beanId: id,
|
|
31788
|
+
deleted: false,
|
|
31789
|
+
error: "Only draft and scrapped beans are deletable unless force=true"
|
|
31790
|
+
});
|
|
31791
|
+
continue;
|
|
31792
|
+
}
|
|
31793
|
+
try {
|
|
31794
|
+
await backend.delete(id);
|
|
31795
|
+
results.push({ beanId: id, deleted: true });
|
|
31796
|
+
} catch (error48) {
|
|
31797
|
+
results.push({
|
|
31798
|
+
beanId: id,
|
|
31799
|
+
deleted: false,
|
|
31800
|
+
error: error48.message
|
|
31801
|
+
});
|
|
31802
|
+
}
|
|
31803
|
+
}
|
|
31804
|
+
return makeTextAndStructured({
|
|
31805
|
+
results,
|
|
31806
|
+
requestedCount: ids.length,
|
|
31807
|
+
deletedCount: results.filter((r) => r.deleted).length,
|
|
31808
|
+
failedCount: results.filter((r) => !r.deleted).length
|
|
31809
|
+
});
|
|
31810
|
+
};
|
|
31811
|
+
}
|
|
31812
|
+
function bulkCreateHandler(backend) {
|
|
31813
|
+
return async (input) => {
|
|
31814
|
+
const results = await backend.bulkCreate(input.beans, input.parent);
|
|
31815
|
+
return makeTextAndStructured({
|
|
31816
|
+
results,
|
|
31817
|
+
requestedCount: input.beans.length,
|
|
31818
|
+
successCount: results.filter((r) => r.bean).length,
|
|
31819
|
+
failedCount: results.filter((r) => r.error).length
|
|
31820
|
+
});
|
|
31821
|
+
};
|
|
31822
|
+
}
|
|
31823
|
+
function bulkUpdateHandler(backend) {
|
|
31824
|
+
return async (input) => {
|
|
31825
|
+
const results = await backend.bulkUpdate(input.beans, input.parent);
|
|
31826
|
+
return makeTextAndStructured({
|
|
31827
|
+
results,
|
|
31828
|
+
requestedCount: input.beans.length,
|
|
31829
|
+
successCount: results.filter((r) => r.bean).length,
|
|
31830
|
+
failedCount: results.filter((r) => r.error).length
|
|
31831
|
+
});
|
|
31371
31832
|
};
|
|
31372
31833
|
}
|
|
31373
31834
|
function queryHandler(backend) {
|
|
@@ -31428,7 +31889,12 @@ function registerTools(server, backend) {
|
|
|
31428
31889
|
{
|
|
31429
31890
|
title: "View Bean",
|
|
31430
31891
|
description: "Fetch full bean details by ID.",
|
|
31431
|
-
inputSchema: external_exports3.object({
|
|
31892
|
+
inputSchema: external_exports3.object({
|
|
31893
|
+
beanId: external_exports3.string().min(1).max(MAX_ID_LENGTH).optional(),
|
|
31894
|
+
beanIds: external_exports3.array(external_exports3.string().min(1).max(MAX_ID_LENGTH)).optional()
|
|
31895
|
+
}).refine((input) => Boolean(input.beanId) || Array.isArray(input.beanIds) && input.beanIds.length > 0, {
|
|
31896
|
+
message: "Either beanId or beanIds must be provided"
|
|
31897
|
+
}),
|
|
31432
31898
|
annotations: {
|
|
31433
31899
|
readOnlyHint: true,
|
|
31434
31900
|
destructiveHint: false,
|
|
@@ -31448,7 +31914,8 @@ function registerTools(server, backend) {
|
|
|
31448
31914
|
type: external_exports3.string().min(1).max(MAX_METADATA_LENGTH),
|
|
31449
31915
|
status: external_exports3.string().max(MAX_METADATA_LENGTH).optional(),
|
|
31450
31916
|
priority: external_exports3.string().max(MAX_METADATA_LENGTH).optional(),
|
|
31451
|
-
|
|
31917
|
+
body: external_exports3.string().max(MAX_DESCRIPTION_LENGTH).optional().describe("Body markdown content"),
|
|
31918
|
+
description: external_exports3.string().max(MAX_DESCRIPTION_LENGTH).optional().describe("Deprecated alias for body"),
|
|
31452
31919
|
parent: external_exports3.string().max(MAX_ID_LENGTH).optional()
|
|
31453
31920
|
}),
|
|
31454
31921
|
annotations: {
|
|
@@ -31517,8 +31984,21 @@ function registerTools(server, backend) {
|
|
|
31517
31984
|
clearParent: external_exports3.boolean().optional(),
|
|
31518
31985
|
blocking: external_exports3.array(external_exports3.string().max(MAX_ID_LENGTH)).optional(),
|
|
31519
31986
|
blockedBy: external_exports3.array(external_exports3.string().max(MAX_ID_LENGTH)).optional(),
|
|
31520
|
-
body: external_exports3.string().max(MAX_DESCRIPTION_LENGTH).optional()
|
|
31521
|
-
|
|
31987
|
+
body: external_exports3.string().max(MAX_DESCRIPTION_LENGTH).optional(),
|
|
31988
|
+
bodyAppend: external_exports3.string().max(MAX_DESCRIPTION_LENGTH).optional(),
|
|
31989
|
+
bodyReplace: external_exports3.array(
|
|
31990
|
+
external_exports3.object({
|
|
31991
|
+
old: external_exports3.string().max(MAX_DESCRIPTION_LENGTH),
|
|
31992
|
+
new: external_exports3.string().max(MAX_DESCRIPTION_LENGTH)
|
|
31993
|
+
})
|
|
31994
|
+
).optional(),
|
|
31995
|
+
ifMatch: external_exports3.string().max(MAX_METADATA_LENGTH).optional()
|
|
31996
|
+
}).refine(
|
|
31997
|
+
(input) => !(input.body !== void 0 && (input.bodyAppend !== void 0 || input.bodyReplace !== void 0)),
|
|
31998
|
+
{
|
|
31999
|
+
message: "body cannot be combined with bodyAppend/bodyReplace"
|
|
32000
|
+
}
|
|
32001
|
+
),
|
|
31522
32002
|
annotations: {
|
|
31523
32003
|
readOnlyHint: false,
|
|
31524
32004
|
destructiveHint: false,
|
|
@@ -31534,8 +32014,11 @@ function registerTools(server, backend) {
|
|
|
31534
32014
|
title: "Delete Bean",
|
|
31535
32015
|
description: "Delete a bean (intended for draft/scrapped beans).",
|
|
31536
32016
|
inputSchema: external_exports3.object({
|
|
31537
|
-
beanId: external_exports3.string().min(1).max(MAX_ID_LENGTH),
|
|
32017
|
+
beanId: external_exports3.string().min(1).max(MAX_ID_LENGTH).optional(),
|
|
32018
|
+
beanIds: external_exports3.array(external_exports3.string().min(1).max(MAX_ID_LENGTH)).optional(),
|
|
31538
32019
|
force: external_exports3.boolean().default(false)
|
|
32020
|
+
}).refine((input) => Boolean(input.beanId) || Array.isArray(input.beanIds) && input.beanIds.length > 0, {
|
|
32021
|
+
message: "Either beanId or beanIds must be provided"
|
|
31539
32022
|
}),
|
|
31540
32023
|
annotations: {
|
|
31541
32024
|
readOnlyHint: false,
|
|
@@ -31546,13 +32029,75 @@ function registerTools(server, backend) {
|
|
|
31546
32029
|
},
|
|
31547
32030
|
deleteHandler(backend)
|
|
31548
32031
|
);
|
|
32032
|
+
const beanCreateItemSchema = external_exports3.object({
|
|
32033
|
+
title: external_exports3.string().min(1).max(MAX_TITLE_LENGTH),
|
|
32034
|
+
type: external_exports3.string().min(1).max(MAX_METADATA_LENGTH),
|
|
32035
|
+
status: external_exports3.string().max(MAX_METADATA_LENGTH).optional(),
|
|
32036
|
+
priority: external_exports3.string().max(MAX_METADATA_LENGTH).optional(),
|
|
32037
|
+
body: external_exports3.string().max(MAX_DESCRIPTION_LENGTH).optional().describe("Body markdown content"),
|
|
32038
|
+
description: external_exports3.string().max(MAX_DESCRIPTION_LENGTH).optional().describe("Deprecated alias for body"),
|
|
32039
|
+
parent: external_exports3.string().max(MAX_ID_LENGTH).optional().describe("Override the top-level parent for this item")
|
|
32040
|
+
});
|
|
32041
|
+
server.registerTool(
|
|
32042
|
+
"beans_bulk_create",
|
|
32043
|
+
{
|
|
32044
|
+
title: "Bulk Create Beans",
|
|
32045
|
+
description: "Create multiple beans in one call. Optionally assign all of them (or a subset) to a shared parent.",
|
|
32046
|
+
inputSchema: external_exports3.object({
|
|
32047
|
+
beans: external_exports3.array(beanCreateItemSchema).min(1),
|
|
32048
|
+
parent: external_exports3.string().max(MAX_ID_LENGTH).optional().describe("Default parent ID applied to any bean that does not specify its own parent")
|
|
32049
|
+
}),
|
|
32050
|
+
annotations: {
|
|
32051
|
+
readOnlyHint: false,
|
|
32052
|
+
destructiveHint: false,
|
|
32053
|
+
idempotentHint: false,
|
|
32054
|
+
openWorldHint: false
|
|
32055
|
+
}
|
|
32056
|
+
},
|
|
32057
|
+
bulkCreateHandler(backend)
|
|
32058
|
+
);
|
|
32059
|
+
const beanUpdateItemSchema = external_exports3.object({
|
|
32060
|
+
beanId: external_exports3.string().min(1).max(MAX_ID_LENGTH),
|
|
32061
|
+
status: external_exports3.string().max(MAX_METADATA_LENGTH).optional(),
|
|
32062
|
+
type: external_exports3.string().max(MAX_METADATA_LENGTH).optional(),
|
|
32063
|
+
priority: external_exports3.string().max(MAX_METADATA_LENGTH).optional(),
|
|
32064
|
+
parent: external_exports3.string().max(MAX_ID_LENGTH).optional().describe("Override the top-level parent for this item"),
|
|
32065
|
+
clearParent: external_exports3.boolean().optional(),
|
|
32066
|
+
blocking: external_exports3.array(external_exports3.string().max(MAX_ID_LENGTH)).optional(),
|
|
32067
|
+
blockedBy: external_exports3.array(external_exports3.string().max(MAX_ID_LENGTH)).optional(),
|
|
32068
|
+
body: external_exports3.string().max(MAX_DESCRIPTION_LENGTH).optional(),
|
|
32069
|
+
bodyAppend: external_exports3.string().max(MAX_DESCRIPTION_LENGTH).optional(),
|
|
32070
|
+
bodyReplace: external_exports3.array(external_exports3.object({ old: external_exports3.string().max(MAX_DESCRIPTION_LENGTH), new: external_exports3.string().max(MAX_DESCRIPTION_LENGTH) })).optional(),
|
|
32071
|
+
ifMatch: external_exports3.string().max(MAX_METADATA_LENGTH).optional()
|
|
32072
|
+
}).refine(
|
|
32073
|
+
(input) => !(input.body !== void 0 && (input.bodyAppend !== void 0 || input.bodyReplace !== void 0)),
|
|
32074
|
+
{ message: "body cannot be combined with bodyAppend/bodyReplace" }
|
|
32075
|
+
);
|
|
32076
|
+
server.registerTool(
|
|
32077
|
+
"beans_bulk_update",
|
|
32078
|
+
{
|
|
32079
|
+
title: "Bulk Update Beans",
|
|
32080
|
+
description: "Update multiple beans in one call. Optionally assign all of them (or a subset) to a shared parent.",
|
|
32081
|
+
inputSchema: external_exports3.object({
|
|
32082
|
+
beans: external_exports3.array(beanUpdateItemSchema).min(1),
|
|
32083
|
+
parent: external_exports3.string().max(MAX_ID_LENGTH).optional().describe("Default parent ID applied to any bean that does not specify its own parent")
|
|
32084
|
+
}),
|
|
32085
|
+
annotations: {
|
|
32086
|
+
readOnlyHint: false,
|
|
32087
|
+
destructiveHint: false,
|
|
32088
|
+
idempotentHint: false,
|
|
32089
|
+
openWorldHint: false
|
|
32090
|
+
}
|
|
32091
|
+
},
|
|
32092
|
+
bulkUpdateHandler(backend)
|
|
32093
|
+
);
|
|
31549
32094
|
server.registerTool(
|
|
31550
32095
|
"beans_query",
|
|
31551
32096
|
{
|
|
31552
32097
|
title: "Query Beans",
|
|
31553
32098
|
description: "Unified query tool for refresh, filter, search, and sort operations.",
|
|
31554
32099
|
inputSchema: external_exports3.object({
|
|
31555
|
-
operation: external_exports3.enum(["refresh", "filter", "search", "sort", "llm_context", "open_config"]).default("refresh"),
|
|
32100
|
+
operation: external_exports3.enum(["refresh", "filter", "search", "sort", "ready", "llm_context", "open_config"]).default("refresh"),
|
|
31556
32101
|
mode: external_exports3.enum(["status-priority-type-title", "updated", "created", "id"]).optional(),
|
|
31557
32102
|
statuses: external_exports3.array(external_exports3.string().max(MAX_METADATA_LENGTH)).nullable().optional(),
|
|
31558
32103
|
types: external_exports3.array(external_exports3.string().max(MAX_METADATA_LENGTH)).nullable().optional(),
|
|
@@ -31631,9 +32176,21 @@ var MutableBackend = class {
|
|
|
31631
32176
|
delete(id) {
|
|
31632
32177
|
return this.inner.delete(id);
|
|
31633
32178
|
}
|
|
32179
|
+
bulkCreate(beans, defaultParent) {
|
|
32180
|
+
return this.inner.bulkCreate(beans, defaultParent);
|
|
32181
|
+
}
|
|
32182
|
+
bulkUpdate(beans, defaultParent) {
|
|
32183
|
+
return this.inner.bulkUpdate(beans, defaultParent);
|
|
32184
|
+
}
|
|
31634
32185
|
openConfig() {
|
|
31635
32186
|
return this.inner.openConfig();
|
|
31636
32187
|
}
|
|
32188
|
+
primeInstructions() {
|
|
32189
|
+
return this.inner.primeInstructions?.() ?? Promise.resolve("");
|
|
32190
|
+
}
|
|
32191
|
+
writeInstructions(instructions) {
|
|
32192
|
+
return this.inner.writeInstructions?.(instructions) ?? Promise.resolve(null);
|
|
32193
|
+
}
|
|
31637
32194
|
graphqlSchema() {
|
|
31638
32195
|
return this.inner.graphqlSchema();
|
|
31639
32196
|
}
|
|
@@ -31671,7 +32228,7 @@ async function createBeansMcpServer(opts) {
|
|
|
31671
32228
|
const backend = opts.backend || new BeansCliBackend2(opts.workspaceRoot, opts.cliPath || "beans", opts.logDir);
|
|
31672
32229
|
const server = new McpServer({
|
|
31673
32230
|
name: opts.name || "beans-mcp-server",
|
|
31674
|
-
version: opts.version ||
|
|
32231
|
+
version: opts.version || PACKAGE_VERSION
|
|
31675
32232
|
});
|
|
31676
32233
|
registerTools(server, backend);
|
|
31677
32234
|
return { server, backend };
|
|
@@ -31743,17 +32300,17 @@ function parseCliArgs(argv) {
|
|
|
31743
32300
|
}
|
|
31744
32301
|
return { workspaceRoot, workspaceExplicit, cliPath, port, logDir };
|
|
31745
32302
|
}
|
|
31746
|
-
async function startBeansMcpServer(argv, _resolveRoots) {
|
|
32303
|
+
async function startBeansMcpServer(argv, _resolveRoots, _detectBeansVersion) {
|
|
31747
32304
|
const { BeansCliBackend: BeansCliBackend2 } = await Promise.resolve().then(() => (init_backend(), backend_exports));
|
|
31748
32305
|
const { StdioServerTransport: StdioServerTransport2 } = await Promise.resolve().then(() => (init_stdio2(), stdio_exports));
|
|
31749
32306
|
const { workspaceRoot, workspaceExplicit, cliPath, port, logDir } = parseCliArgs(argv);
|
|
32307
|
+
let effectiveWorkspaceRoot = workspaceRoot;
|
|
31750
32308
|
process.env.BEANS_VSCODE_MCP_PORT = String(port);
|
|
31751
32309
|
process.env.BEANS_MCP_PORT = String(port);
|
|
31752
32310
|
try {
|
|
31753
|
-
const version2 = package_default.version ?? "0.0.0-dev";
|
|
31754
32311
|
const workspaceLabel = workspaceExplicit ? workspaceRoot : "(auto from roots)";
|
|
31755
32312
|
console.error(
|
|
31756
|
-
`[beans-mcp] v${
|
|
32313
|
+
`[beans-mcp] v${PACKAGE_VERSION} starting (port=${port}, workspace=${workspaceLabel}, cli=${cliPath}, logDir=${logDir})`
|
|
31757
32314
|
);
|
|
31758
32315
|
} catch {
|
|
31759
32316
|
}
|
|
@@ -31770,13 +32327,17 @@ async function startBeansMcpServer(argv, _resolveRoots) {
|
|
|
31770
32327
|
const resolver = _resolveRoots ?? resolveWorkspaceFromRoots;
|
|
31771
32328
|
const rootPath = await resolver(server);
|
|
31772
32329
|
if (rootPath) {
|
|
31773
|
-
mutable.setInner(new BeansCliBackend2(rootPath, cliPath));
|
|
32330
|
+
mutable.setInner(new BeansCliBackend2(rootPath, cliPath, logDir));
|
|
32331
|
+
effectiveWorkspaceRoot = rootPath;
|
|
31774
32332
|
try {
|
|
31775
32333
|
console.error(`[beans-mcp] workspace resolved from roots: ${rootPath}`);
|
|
31776
32334
|
} catch {
|
|
31777
32335
|
}
|
|
31778
32336
|
}
|
|
31779
32337
|
}
|
|
32338
|
+
const beansVersionDetector = _detectBeansVersion ?? detectBeansCliVersion;
|
|
32339
|
+
void checkVersionCompatibility(cliPath, effectiveWorkspaceRoot, beansVersionDetector).catch(() => {
|
|
32340
|
+
});
|
|
31780
32341
|
}
|
|
31781
32342
|
|
|
31782
32343
|
// src/index.ts
|