@lovelybunch/mcp 1.0.50 → 1.0.52
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/dist/proposals-tool.js +24 -8
- package/package.json +2 -2
- package/src/proposals-tool.ts +24 -8
- package/dist/server.d.ts +0 -2
- package/dist/server.js +0 -155
package/dist/proposals-tool.js
CHANGED
|
@@ -10,7 +10,7 @@ export const listProposalsTool = {
|
|
|
10
10
|
properties: {
|
|
11
11
|
status: {
|
|
12
12
|
type: "string",
|
|
13
|
-
enum: ["draft", "review", "approved", "
|
|
13
|
+
enum: ["draft", "proposed", "in-review", "code-complete", "approved", "merged", "rejected"],
|
|
14
14
|
description: "Filter by proposal status"
|
|
15
15
|
},
|
|
16
16
|
priority: {
|
|
@@ -53,7 +53,7 @@ export const proposalsTool = {
|
|
|
53
53
|
properties: {
|
|
54
54
|
status: {
|
|
55
55
|
type: "string",
|
|
56
|
-
enum: ["draft", "review", "approved", "
|
|
56
|
+
enum: ["draft", "proposed", "in-review", "code-complete", "approved", "merged", "rejected"],
|
|
57
57
|
description: "Filter by proposal status"
|
|
58
58
|
},
|
|
59
59
|
author: {
|
|
@@ -96,13 +96,28 @@ export const proposalsTool = {
|
|
|
96
96
|
name: { type: "string" },
|
|
97
97
|
email: { type: "string" },
|
|
98
98
|
role: { type: "string" },
|
|
99
|
-
type: { type: "string", enum: ["human", "
|
|
99
|
+
type: { type: "string", enum: ["human", "agent"] }
|
|
100
100
|
}
|
|
101
101
|
},
|
|
102
102
|
planSteps: {
|
|
103
103
|
type: "array",
|
|
104
|
-
|
|
105
|
-
|
|
104
|
+
description: "Implementation plan steps. Each item may be a string (description) or an object with fields.",
|
|
105
|
+
items: {
|
|
106
|
+
oneOf: [
|
|
107
|
+
{ type: "string", description: "Step description" },
|
|
108
|
+
{
|
|
109
|
+
type: "object",
|
|
110
|
+
properties: {
|
|
111
|
+
id: { type: "string", description: "Step identifier (optional)" },
|
|
112
|
+
description: { type: "string", description: "Human-readable step description" },
|
|
113
|
+
status: { type: "string", enum: ["pending", "in-progress", "completed", "failed"], description: "Execution status" },
|
|
114
|
+
command: { type: "string", description: "Optional command to execute" },
|
|
115
|
+
expectedOutcome: { type: "string", description: "Expected outcome of the step" }
|
|
116
|
+
},
|
|
117
|
+
required: ["description"]
|
|
118
|
+
}
|
|
119
|
+
]
|
|
120
|
+
}
|
|
106
121
|
},
|
|
107
122
|
evidence: {
|
|
108
123
|
type: "array",
|
|
@@ -135,13 +150,13 @@ export const proposalsTool = {
|
|
|
135
150
|
properties: {
|
|
136
151
|
strategy: {
|
|
137
152
|
type: "string",
|
|
138
|
-
enum: ["immediate", "gradual", "
|
|
153
|
+
enum: ["immediate", "gradual", "scheduled", "gated"]
|
|
139
154
|
}
|
|
140
155
|
}
|
|
141
156
|
},
|
|
142
157
|
status: {
|
|
143
158
|
type: "string",
|
|
144
|
-
enum: ["draft", "review", "approved", "
|
|
159
|
+
enum: ["draft", "proposed", "in-review", "code-complete", "approved", "merged", "rejected"],
|
|
145
160
|
description: "Current status of the proposal"
|
|
146
161
|
},
|
|
147
162
|
metadata: {
|
|
@@ -169,7 +184,8 @@ export const proposalsTool = {
|
|
|
169
184
|
type: "string",
|
|
170
185
|
description: "Reference to related product specification"
|
|
171
186
|
}
|
|
172
|
-
}
|
|
187
|
+
},
|
|
188
|
+
required: ["intent", "content"]
|
|
173
189
|
}
|
|
174
190
|
},
|
|
175
191
|
required: ["operation"]
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@lovelybunch/mcp",
|
|
3
|
-
"version": "1.0.
|
|
3
|
+
"version": "1.0.52",
|
|
4
4
|
"description": "MCP tools for Coconut",
|
|
5
5
|
"main": "dist/index.js",
|
|
6
6
|
"type": "module",
|
|
@@ -9,7 +9,7 @@
|
|
|
9
9
|
"dev": "tsc --watch"
|
|
10
10
|
},
|
|
11
11
|
"dependencies": {
|
|
12
|
-
"@lovelybunch/types": "^1.0.
|
|
12
|
+
"@lovelybunch/types": "^1.0.52",
|
|
13
13
|
"hono": "^4.0.0"
|
|
14
14
|
},
|
|
15
15
|
"devDependencies": {
|
package/src/proposals-tool.ts
CHANGED
|
@@ -27,7 +27,7 @@ export const listProposalsTool: MCPTool = {
|
|
|
27
27
|
properties: {
|
|
28
28
|
status: {
|
|
29
29
|
type: "string",
|
|
30
|
-
enum: ["draft", "review", "approved", "
|
|
30
|
+
enum: ["draft", "proposed", "in-review", "code-complete", "approved", "merged", "rejected"],
|
|
31
31
|
description: "Filter by proposal status"
|
|
32
32
|
},
|
|
33
33
|
priority: {
|
|
@@ -71,7 +71,7 @@ export const proposalsTool: MCPTool = {
|
|
|
71
71
|
properties: {
|
|
72
72
|
status: {
|
|
73
73
|
type: "string",
|
|
74
|
-
enum: ["draft", "review", "approved", "
|
|
74
|
+
enum: ["draft", "proposed", "in-review", "code-complete", "approved", "merged", "rejected"],
|
|
75
75
|
description: "Filter by proposal status"
|
|
76
76
|
},
|
|
77
77
|
author: {
|
|
@@ -114,13 +114,28 @@ export const proposalsTool: MCPTool = {
|
|
|
114
114
|
name: { type: "string" },
|
|
115
115
|
email: { type: "string" },
|
|
116
116
|
role: { type: "string" },
|
|
117
|
-
type: { type: "string", enum: ["human", "
|
|
117
|
+
type: { type: "string", enum: ["human", "agent"] }
|
|
118
118
|
}
|
|
119
119
|
},
|
|
120
120
|
planSteps: {
|
|
121
121
|
type: "array",
|
|
122
|
-
|
|
123
|
-
|
|
122
|
+
description: "Implementation plan steps. Each item may be a string (description) or an object with fields.",
|
|
123
|
+
items: {
|
|
124
|
+
oneOf: [
|
|
125
|
+
{ type: "string", description: "Step description" },
|
|
126
|
+
{
|
|
127
|
+
type: "object",
|
|
128
|
+
properties: {
|
|
129
|
+
id: { type: "string", description: "Step identifier (optional)" },
|
|
130
|
+
description: { type: "string", description: "Human-readable step description" },
|
|
131
|
+
status: { type: "string", enum: ["pending", "in-progress", "completed", "failed"], description: "Execution status" },
|
|
132
|
+
command: { type: "string", description: "Optional command to execute" },
|
|
133
|
+
expectedOutcome: { type: "string", description: "Expected outcome of the step" }
|
|
134
|
+
},
|
|
135
|
+
required: ["description"]
|
|
136
|
+
}
|
|
137
|
+
]
|
|
138
|
+
}
|
|
124
139
|
},
|
|
125
140
|
evidence: {
|
|
126
141
|
type: "array",
|
|
@@ -153,13 +168,13 @@ export const proposalsTool: MCPTool = {
|
|
|
153
168
|
properties: {
|
|
154
169
|
strategy: {
|
|
155
170
|
type: "string",
|
|
156
|
-
enum: ["immediate", "gradual", "
|
|
171
|
+
enum: ["immediate", "gradual", "scheduled", "gated"]
|
|
157
172
|
}
|
|
158
173
|
}
|
|
159
174
|
},
|
|
160
175
|
status: {
|
|
161
176
|
type: "string",
|
|
162
|
-
enum: ["draft", "review", "approved", "
|
|
177
|
+
enum: ["draft", "proposed", "in-review", "code-complete", "approved", "merged", "rejected"],
|
|
163
178
|
description: "Current status of the proposal"
|
|
164
179
|
},
|
|
165
180
|
metadata: {
|
|
@@ -187,7 +202,8 @@ export const proposalsTool: MCPTool = {
|
|
|
187
202
|
type: "string",
|
|
188
203
|
description: "Reference to related product specification"
|
|
189
204
|
}
|
|
190
|
-
}
|
|
205
|
+
},
|
|
206
|
+
required: ["intent", "content"]
|
|
191
207
|
}
|
|
192
208
|
},
|
|
193
209
|
required: ["operation"]
|
package/dist/server.d.ts
DELETED
package/dist/server.js
DELETED
|
@@ -1,155 +0,0 @@
|
|
|
1
|
-
#!/usr/bin/env node
|
|
2
|
-
import { createInterface } from 'readline';
|
|
3
|
-
import { stdin as input, stdout as output } from 'process';
|
|
4
|
-
import fs from 'fs';
|
|
5
|
-
import path from 'path';
|
|
6
|
-
function send(id, result, error) {
|
|
7
|
-
const payload = { jsonrpc: '2.0', id };
|
|
8
|
-
if (error)
|
|
9
|
-
payload.error = error;
|
|
10
|
-
else
|
|
11
|
-
payload.result = result;
|
|
12
|
-
output.write(JSON.stringify(payload) + '\n');
|
|
13
|
-
}
|
|
14
|
-
function resolveNutPath() {
|
|
15
|
-
if (process.env.GAIT_DATA_PATH)
|
|
16
|
-
return path.join(process.env.GAIT_DATA_PATH, '.nut');
|
|
17
|
-
// Try to find nearest .nut folder upward from cwd
|
|
18
|
-
let dir = process.cwd();
|
|
19
|
-
for (;;) {
|
|
20
|
-
const p = path.join(dir, '.nut');
|
|
21
|
-
if (fs.existsSync(p))
|
|
22
|
-
return p;
|
|
23
|
-
const parent = path.dirname(dir);
|
|
24
|
-
if (parent === dir)
|
|
25
|
-
break;
|
|
26
|
-
dir = parent;
|
|
27
|
-
}
|
|
28
|
-
return path.join(process.cwd(), '.nut');
|
|
29
|
-
}
|
|
30
|
-
function listProposalFiles() {
|
|
31
|
-
const base = resolveNutPath();
|
|
32
|
-
const p = path.join(base, 'proposals');
|
|
33
|
-
try {
|
|
34
|
-
return fs.readdirSync(p).filter((f) => f.endsWith('.md'));
|
|
35
|
-
}
|
|
36
|
-
catch {
|
|
37
|
-
return [];
|
|
38
|
-
}
|
|
39
|
-
}
|
|
40
|
-
function readProposal(id) {
|
|
41
|
-
const base = resolveNutPath();
|
|
42
|
-
const fp = path.join(base, 'proposals', `${id}.md`);
|
|
43
|
-
try {
|
|
44
|
-
const content = fs.readFileSync(fp, 'utf-8');
|
|
45
|
-
// Naive frontmatter parse (best effort, no YAML dependency)
|
|
46
|
-
let frontmatter;
|
|
47
|
-
if (content.startsWith('---')) {
|
|
48
|
-
const end = content.indexOf('\n---', 3);
|
|
49
|
-
if (end > 0) {
|
|
50
|
-
const fm = content.slice(3, end).split('\n');
|
|
51
|
-
frontmatter = {};
|
|
52
|
-
for (const line of fm) {
|
|
53
|
-
const m = /^([A-Za-z0-9_\-]+):\s*(.*)$/.exec(line.trim());
|
|
54
|
-
if (m)
|
|
55
|
-
frontmatter[m[1]] = m[2];
|
|
56
|
-
}
|
|
57
|
-
}
|
|
58
|
-
}
|
|
59
|
-
return { content, frontmatter };
|
|
60
|
-
}
|
|
61
|
-
catch {
|
|
62
|
-
return null;
|
|
63
|
-
}
|
|
64
|
-
}
|
|
65
|
-
const tools = [
|
|
66
|
-
{
|
|
67
|
-
name: 'list_proposals',
|
|
68
|
-
description: 'List all change proposals with basic metadata',
|
|
69
|
-
input_schema: {
|
|
70
|
-
type: 'object',
|
|
71
|
-
properties: {
|
|
72
|
-
filters: { type: 'object' },
|
|
73
|
-
},
|
|
74
|
-
},
|
|
75
|
-
},
|
|
76
|
-
{
|
|
77
|
-
name: 'change_proposals',
|
|
78
|
-
description: 'Manage change proposals (list, get)',
|
|
79
|
-
input_schema: {
|
|
80
|
-
type: 'object',
|
|
81
|
-
properties: {
|
|
82
|
-
operation: { type: 'string', enum: ['list', 'get'] },
|
|
83
|
-
id: { type: 'string' },
|
|
84
|
-
filters: { type: 'object' },
|
|
85
|
-
},
|
|
86
|
-
required: ['operation'],
|
|
87
|
-
},
|
|
88
|
-
},
|
|
89
|
-
];
|
|
90
|
-
async function handleCall(params) {
|
|
91
|
-
const name = params?.name || params?.tool?.name;
|
|
92
|
-
const args = params?.arguments || params?.tool?.input || {};
|
|
93
|
-
switch (name) {
|
|
94
|
-
case 'list_proposals': {
|
|
95
|
-
const files = listProposalFiles();
|
|
96
|
-
const data = files.map((f) => ({ id: f.replace(/\.md$/, ''), title: f.replace(/\.md$/, '') }));
|
|
97
|
-
return { success: true, data, message: `Found ${data.length} proposals` };
|
|
98
|
-
}
|
|
99
|
-
case 'change_proposals': {
|
|
100
|
-
const op = args.operation;
|
|
101
|
-
if (op === 'list') {
|
|
102
|
-
const files = listProposalFiles();
|
|
103
|
-
const data = files.map((f) => ({ id: f.replace(/\.md$/, ''), title: f.replace(/\.md$/, '') }));
|
|
104
|
-
return { success: true, data, message: `Found ${data.length} proposals` };
|
|
105
|
-
}
|
|
106
|
-
if (op === 'get') {
|
|
107
|
-
if (!args.id)
|
|
108
|
-
return { success: false, error: 'Proposal ID required' };
|
|
109
|
-
const p = readProposal(args.id);
|
|
110
|
-
if (!p)
|
|
111
|
-
return { success: false, error: 'Proposal not found' };
|
|
112
|
-
return { success: true, data: { id: args.id, content: p.content, frontmatter: p.frontmatter || {} } };
|
|
113
|
-
}
|
|
114
|
-
return { success: false, error: 'Operation not implemented' };
|
|
115
|
-
}
|
|
116
|
-
default:
|
|
117
|
-
return { success: false, error: 'Unknown tool' };
|
|
118
|
-
}
|
|
119
|
-
}
|
|
120
|
-
function start() {
|
|
121
|
-
const rl = createInterface({ input });
|
|
122
|
-
rl.on('line', async (line) => {
|
|
123
|
-
let msg;
|
|
124
|
-
try {
|
|
125
|
-
msg = JSON.parse(line);
|
|
126
|
-
}
|
|
127
|
-
catch {
|
|
128
|
-
return; // ignore invalid JSON
|
|
129
|
-
}
|
|
130
|
-
const { id, method, params } = msg || {};
|
|
131
|
-
try {
|
|
132
|
-
if (method === 'initialize') {
|
|
133
|
-
send(id, {
|
|
134
|
-
serverInfo: { name: '@lovelybunch/mcp-proposals', version: '1.0.0' },
|
|
135
|
-
capabilities: { tools: {} },
|
|
136
|
-
});
|
|
137
|
-
return;
|
|
138
|
-
}
|
|
139
|
-
if (method === 'tools/list') {
|
|
140
|
-
send(id, { tools });
|
|
141
|
-
return;
|
|
142
|
-
}
|
|
143
|
-
if (method === 'tools/call') {
|
|
144
|
-
const result = await handleCall(params);
|
|
145
|
-
send(id, { content: [{ type: 'text', text: JSON.stringify(result) }] });
|
|
146
|
-
return;
|
|
147
|
-
}
|
|
148
|
-
send(id, undefined, { code: -32601, message: 'Method not found' });
|
|
149
|
-
}
|
|
150
|
-
catch (e) {
|
|
151
|
-
send(id, undefined, { code: -32000, message: e?.message || 'Server error' });
|
|
152
|
-
}
|
|
153
|
-
});
|
|
154
|
-
}
|
|
155
|
-
start();
|