@selfagency/beans-mcp 0.1.1 → 0.1.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.
Files changed (44) hide show
  1. package/{dist/beans-mcp-server.cjs → beans-mcp-server.cjs} +8 -4
  2. package/{dist/index.cjs → index.cjs} +8 -4
  3. package/{dist/index.d.ts → index.d.ts} +2 -1
  4. package/{dist/index.js → index.js} +8 -4
  5. package/package.json +27 -64
  6. package/.beans.yml +0 -6
  7. package/.claude/settings.local.json +0 -18
  8. package/.editorconfig +0 -13
  9. package/.github/workflows/release.yml +0 -235
  10. package/.github/workflows/test.yml +0 -80
  11. package/.husky/pre-commit +0 -1
  12. package/.nvmrc +0 -1
  13. package/.oxfmtrc.json +0 -11
  14. package/.oxlintrc.json +0 -37
  15. package/.vscode/settings.json +0 -3
  16. package/CHANGELOG.md +0 -140
  17. package/CONTRIBUTING.md +0 -139
  18. package/dist/README.md +0 -307
  19. package/dist/beans-mcp-server.cjs.map +0 -1
  20. package/dist/index.cjs.map +0 -1
  21. package/dist/index.js.map +0 -1
  22. package/dist/package.json +0 -43
  23. package/pnpm-workspace.yaml +0 -2
  24. package/scripts/release.js +0 -433
  25. package/scripts/write-dist-package.js +0 -53
  26. package/src/cli.ts +0 -14
  27. package/src/index.ts +0 -21
  28. package/src/internal/graphql.ts +0 -33
  29. package/src/internal/queryHelpers.ts +0 -157
  30. package/src/server/BeansMcpServer.ts +0 -600
  31. package/src/server/backend.ts +0 -358
  32. package/src/test/BeansMcpServer.test.ts +0 -514
  33. package/src/test/handlers.unit.test.ts +0 -184
  34. package/src/test/parseCliArgs.test.ts +0 -69
  35. package/src/test/protocol.e2e.test.ts +0 -884
  36. package/src/test/queryHelpers.test.ts +0 -524
  37. package/src/test/startBeansMcpServer.test.ts +0 -146
  38. package/src/test/tools-integration.test.ts +0 -912
  39. package/src/test/utils.test.ts +0 -80
  40. package/src/types.ts +0 -46
  41. package/src/utils.ts +0 -20
  42. package/tsconfig.json +0 -24
  43. package/tsup.config.ts +0 -42
  44. package/vitest.config.ts +0 -18
@@ -1,157 +0,0 @@
1
- import { BeanRecord, SortMode } from '../types';
2
-
3
- export type QueryBackend = {
4
- graphqlSchema?: () => Promise<string>;
5
- writeInstructions?: (instructions: string) => Promise<string | null>;
6
- openConfig?: () => Promise<Record<string, unknown>>;
7
- list(options?: { status?: string[]; type?: string[]; search?: string }): Promise<BeanRecord[]>;
8
- };
9
-
10
- function sortBeansInternal(beans: BeanRecord[], mode: SortMode): BeanRecord[] {
11
- const sorted = [...beans];
12
- const statusWeight: Record<string, number> = {
13
- 'in-progress': 0,
14
- todo: 1,
15
- draft: 2,
16
- completed: 3,
17
- scrapped: 4,
18
- };
19
- const priorityWeight: Record<string, number> = {
20
- critical: 0,
21
- high: 1,
22
- normal: 2,
23
- low: 3,
24
- deferred: 4,
25
- };
26
- const typeWeight: Record<string, number> = {
27
- milestone: 0,
28
- epic: 1,
29
- feature: 2,
30
- bug: 3,
31
- task: 4,
32
- };
33
-
34
- if (mode === 'updated') {
35
- return sorted.sort((a, b) => (b.updatedAt || '').localeCompare(a.updatedAt || ''));
36
- }
37
-
38
- if (mode === 'created') {
39
- return sorted.sort((a, b) => (b.createdAt || '').localeCompare(a.createdAt || ''));
40
- }
41
-
42
- if (mode === 'id') {
43
- return sorted.sort((a, b) => a.id.localeCompare(b.id));
44
- }
45
-
46
- return sorted.sort((a, b) => {
47
- const statusCmp = (statusWeight[a.status] ?? 99) - (statusWeight[b.status] ?? 99);
48
- if (statusCmp !== 0) {
49
- return statusCmp;
50
- }
51
-
52
- const aPriority = a.priority || 'normal';
53
- const bPriority = b.priority || 'normal';
54
- const priorityCmp = (priorityWeight[aPriority] ?? 99) - (priorityWeight[bPriority] ?? 99);
55
- if (priorityCmp !== 0) {
56
- return priorityCmp;
57
- }
58
-
59
- const typeCmp = (typeWeight[a.type] ?? 99) - (typeWeight[b.type] ?? 99);
60
- if (typeCmp !== 0) {
61
- return typeCmp;
62
- }
63
-
64
- return a.title.localeCompare(b.title);
65
- });
66
- }
67
-
68
- export async function handleQueryOperation(
69
- backend: QueryBackend,
70
- params: {
71
- operation: string;
72
- mode?: SortMode;
73
- statuses?: string[] | null;
74
- types?: string[] | null;
75
- search?: string;
76
- tags?: string[] | null;
77
- writeToWorkspaceInstructions?: boolean;
78
- includeClosed?: boolean;
79
- },
80
- ): Promise<{ content: Array<{ type: 'text'; text: string }>; structuredContent: Record<string, unknown> }> {
81
- const { operation, mode, statuses, types, search, tags, writeToWorkspaceInstructions, includeClosed } = params;
82
-
83
- if (operation === 'llm_context') {
84
- const graphqlSchema = typeof backend.graphqlSchema === 'function' ? await backend.graphqlSchema() : '';
85
- const instructionsPath =
86
- writeToWorkspaceInstructions && typeof backend.writeInstructions === 'function'
87
- ? await backend.writeInstructions('')
88
- : null;
89
- return {
90
- content: [
91
- {
92
- type: 'text',
93
- text: JSON.stringify({ graphqlSchema, generatedInstructions: '', instructionsPath }, null, 2),
94
- },
95
- ],
96
- structuredContent: { graphqlSchema, generatedInstructions: '', instructionsPath },
97
- };
98
- }
99
-
100
- if (operation === 'open_config') {
101
- const config = typeof backend.openConfig === 'function' ? await backend.openConfig() : {};
102
- return { content: [{ type: 'text', text: JSON.stringify(config, null, 2) }], structuredContent: config };
103
- }
104
-
105
- const normalizedStatuses = Array.isArray(statuses) ? statuses : undefined;
106
- const normalizedTypes = Array.isArray(types) ? types : undefined;
107
-
108
- if (operation === 'refresh') {
109
- const beans = await backend.list();
110
- return {
111
- content: [{ type: 'text', text: JSON.stringify({ count: beans.length, beans }, null, 2) }],
112
- structuredContent: { count: beans.length, beans },
113
- };
114
- }
115
-
116
- if (operation === 'filter') {
117
- let beans = await backend.list({ status: normalizedStatuses, type: normalizedTypes, search });
118
- if (Array.isArray(tags) && tags.length > 0) {
119
- const tagSet = new Set(tags);
120
- beans = beans.filter((bean: BeanRecord) => (bean.tags || []).some((tag: string) => tagSet.has(tag)));
121
- }
122
- return {
123
- content: [{ type: 'text', text: JSON.stringify({ count: beans.length, beans }, null, 2) }],
124
- structuredContent: { count: beans.length, beans },
125
- };
126
- }
127
-
128
- if (operation === 'search') {
129
- let beans = await backend.list({ search });
130
- if (typeof search === 'string' && search.length > 0) {
131
- const q = search.toLowerCase();
132
- beans = beans.filter((b: BeanRecord) => {
133
- const title = (b.title || '').toLowerCase();
134
- const id = (b.id || '').toLowerCase();
135
- const tagsStr = (b.tags || []).join(' ').toLowerCase();
136
- return title.includes(q) || id.includes(q) || tagsStr.includes(q);
137
- });
138
- }
139
- if (includeClosed === false) {
140
- beans = beans.filter((b: BeanRecord) => b.status !== 'completed' && b.status !== 'scrapped');
141
- }
142
- return {
143
- content: [{ type: 'text', text: JSON.stringify({ query: search, count: beans.length, beans }, null, 2) }],
144
- structuredContent: { query: search, count: beans.length, beans },
145
- };
146
- }
147
-
148
- // sort
149
- const beans = await backend.list({ status: normalizedStatuses, type: normalizedTypes, search });
150
- const sorted = sortBeansInternal(beans, mode ?? 'status-priority-type-title');
151
- return {
152
- content: [{ type: 'text', text: JSON.stringify({ mode, count: beans.length, beans: sorted }, null, 2) }],
153
- structuredContent: { mode, count: beans.length, beans: sorted },
154
- };
155
- }
156
-
157
- export { sortBeansInternal as sortBeans };