senq-mcp 1.1.0 → 1.3.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/dist/index.js +3 -3
- package/dist/setup.js +29 -2
- package/package.json +1 -1
- package/src/index.ts +3 -3
- package/src/setup.ts +32 -2
package/dist/index.js
CHANGED
|
@@ -9,7 +9,7 @@ if (process.argv[2] === "setup") {
|
|
|
9
9
|
await runSetup();
|
|
10
10
|
process.exit(0);
|
|
11
11
|
}
|
|
12
|
-
const server = new Server({ name: "senq-mcp", version: "1.
|
|
12
|
+
const server = new Server({ name: "senq-mcp", version: "1.3.0" }, { capabilities: { tools: {} } });
|
|
13
13
|
server.setRequestHandler(ListToolsRequestSchema, async () => ({
|
|
14
14
|
tools: [
|
|
15
15
|
{
|
|
@@ -289,7 +289,7 @@ server.setRequestHandler(CallToolRequestSchema, async (req) => {
|
|
|
289
289
|
params.limit = String(args.limit);
|
|
290
290
|
if (args?.offset)
|
|
291
291
|
params.offset = String(args.offset);
|
|
292
|
-
const data = await apiGet("/api/
|
|
292
|
+
const data = await apiGet("/api/tasks/team", params);
|
|
293
293
|
const tasks = data.tasks ?? [];
|
|
294
294
|
const total = data.total ?? tasks.length;
|
|
295
295
|
return {
|
|
@@ -308,7 +308,7 @@ server.setRequestHandler(CallToolRequestSchema, async (req) => {
|
|
|
308
308
|
params.projectId = String(args.projectId);
|
|
309
309
|
if (args?.areaId)
|
|
310
310
|
params.areaId = String(args.areaId);
|
|
311
|
-
const data = await apiGet("/api/
|
|
311
|
+
const data = await apiGet("/api/tasks/team", params);
|
|
312
312
|
const allTasks = data.tasks ?? [];
|
|
313
313
|
const dateFrom = args?.dateFrom ? String(args.dateFrom) : undefined;
|
|
314
314
|
const dateTo = args?.dateTo ? String(args.dateTo) : undefined;
|
package/dist/setup.js
CHANGED
|
@@ -23,6 +23,7 @@ const CLIENTS = [
|
|
|
23
23
|
{ id: "claude", label: "Claude Desktop", configPath: getConfigPath("claude") },
|
|
24
24
|
{ id: "cursor", label: "Cursor", configPath: getConfigPath("cursor") },
|
|
25
25
|
{ id: "claudecode", label: "Claude Code", configPath: getConfigPath("claudecode") },
|
|
26
|
+
{ id: "codex", label: "Codex", configPath: path.join(os.homedir(), ".codex", "config.toml") },
|
|
26
27
|
];
|
|
27
28
|
function readHidden(prompt) {
|
|
28
29
|
return new Promise((resolve) => {
|
|
@@ -82,6 +83,27 @@ function mergeConfig(configPath, apiKey) {
|
|
|
82
83
|
fs.mkdirSync(path.dirname(configPath), { recursive: true });
|
|
83
84
|
fs.writeFileSync(configPath, JSON.stringify(config, null, 2) + "\n");
|
|
84
85
|
}
|
|
86
|
+
function mergeCodexConfig(configPath, apiKey) {
|
|
87
|
+
fs.mkdirSync(path.dirname(configPath), { recursive: true });
|
|
88
|
+
let existing = "";
|
|
89
|
+
if (fs.existsSync(configPath)) {
|
|
90
|
+
existing = fs.readFileSync(configPath, "utf8");
|
|
91
|
+
}
|
|
92
|
+
const senqBlock = `[mcp_servers.senq]\ncommand = "npx"\nargs = ["senq-mcp"]\n\n[mcp_servers.senq.env]\nSENQ_API_KEY = "${apiKey}"`;
|
|
93
|
+
if (existing.includes("[mcp_servers.senq]")) {
|
|
94
|
+
// Replace existing senq block
|
|
95
|
+
const updated = existing.replace(/\[mcp_servers\.senq\][\s\S]*?SENQ_API_KEY\s*=\s*"[^"]*"/, senqBlock);
|
|
96
|
+
fs.writeFileSync(configPath, updated);
|
|
97
|
+
}
|
|
98
|
+
else if (existing.includes("[sandbox_workspace_write]")) {
|
|
99
|
+
// Insert before sandbox section
|
|
100
|
+
const updated = existing.replace("[sandbox_workspace_write]", `${senqBlock}\n\n[sandbox_workspace_write]`);
|
|
101
|
+
fs.writeFileSync(configPath, updated);
|
|
102
|
+
}
|
|
103
|
+
else {
|
|
104
|
+
fs.writeFileSync(configPath, existing + (existing.endsWith("\n") || !existing ? "" : "\n") + "\n" + senqBlock + "\n");
|
|
105
|
+
}
|
|
106
|
+
}
|
|
85
107
|
export async function runSetup() {
|
|
86
108
|
console.log("\n🤖 Настройка Senq MCP\n");
|
|
87
109
|
const apiKey = await readHidden("Вставь API-ключ из Senq: ");
|
|
@@ -94,7 +116,7 @@ export async function runSetup() {
|
|
|
94
116
|
const exists = fs.existsSync(c.configPath);
|
|
95
117
|
console.log(` ${i + 1}) ${c.label}${exists ? " (конфиг найден)" : ""}`);
|
|
96
118
|
});
|
|
97
|
-
console.log(` ${CLIENTS.length + 1}) Все
|
|
119
|
+
console.log(` ${CLIENTS.length + 1}) Все четыре\n`);
|
|
98
120
|
const choice = await ask("Введи номер [1]: ", "1");
|
|
99
121
|
const num = parseInt(choice, 10);
|
|
100
122
|
let selected;
|
|
@@ -110,7 +132,12 @@ export async function runSetup() {
|
|
|
110
132
|
console.log("");
|
|
111
133
|
for (const client of selected) {
|
|
112
134
|
try {
|
|
113
|
-
|
|
135
|
+
if (client.id === "codex") {
|
|
136
|
+
mergeCodexConfig(client.configPath, apiKey);
|
|
137
|
+
}
|
|
138
|
+
else {
|
|
139
|
+
mergeConfig(client.configPath, apiKey);
|
|
140
|
+
}
|
|
114
141
|
console.log(` ✅ ${client.label}: ${client.configPath}`);
|
|
115
142
|
}
|
|
116
143
|
catch (err) {
|
package/package.json
CHANGED
package/src/index.ts
CHANGED
|
@@ -15,7 +15,7 @@ if (process.argv[2] === "setup") {
|
|
|
15
15
|
}
|
|
16
16
|
|
|
17
17
|
const server = new Server(
|
|
18
|
-
{ name: "senq-mcp", version: "1.
|
|
18
|
+
{ name: "senq-mcp", version: "1.3.0" },
|
|
19
19
|
{ capabilities: { tools: {} } },
|
|
20
20
|
);
|
|
21
21
|
|
|
@@ -266,7 +266,7 @@ server.setRequestHandler(CallToolRequestSchema, async (req) => {
|
|
|
266
266
|
if (args?.dateTo) params.dateTo = String(args.dateTo);
|
|
267
267
|
if (args?.limit) params.limit = String(args.limit);
|
|
268
268
|
if (args?.offset) params.offset = String(args.offset);
|
|
269
|
-
const data = await apiGet<{ tasks?: unknown[]; total?: number }>("/api/
|
|
269
|
+
const data = await apiGet<{ tasks?: unknown[]; total?: number }>("/api/tasks/team", params);
|
|
270
270
|
const tasks = data.tasks ?? [];
|
|
271
271
|
const total = data.total ?? tasks.length;
|
|
272
272
|
return {
|
|
@@ -289,7 +289,7 @@ server.setRequestHandler(CallToolRequestSchema, async (req) => {
|
|
|
289
289
|
dueDate?: string | null; completedAt?: string | null;
|
|
290
290
|
projectName?: string | null; areaName?: string | null;
|
|
291
291
|
assigneeName?: string | null;
|
|
292
|
-
}>; total?: number }>("/api/
|
|
292
|
+
}>; total?: number }>("/api/tasks/team", params);
|
|
293
293
|
|
|
294
294
|
const allTasks = data.tasks ?? [];
|
|
295
295
|
const dateFrom = args?.dateFrom ? String(args.dateFrom) : undefined;
|
package/src/setup.ts
CHANGED
|
@@ -31,6 +31,7 @@ const CLIENTS: ClientInfo[] = [
|
|
|
31
31
|
{ id: "claude", label: "Claude Desktop", configPath: getConfigPath("claude") },
|
|
32
32
|
{ id: "cursor", label: "Cursor", configPath: getConfigPath("cursor") },
|
|
33
33
|
{ id: "claudecode", label: "Claude Code", configPath: getConfigPath("claudecode") },
|
|
34
|
+
{ id: "codex", label: "Codex", configPath: path.join(os.homedir(), ".codex", "config.toml") },
|
|
34
35
|
];
|
|
35
36
|
|
|
36
37
|
function readHidden(prompt: string): Promise<string> {
|
|
@@ -87,6 +88,31 @@ function mergeConfig(configPath: string, apiKey: string): void {
|
|
|
87
88
|
fs.writeFileSync(configPath, JSON.stringify(config, null, 2) + "\n");
|
|
88
89
|
}
|
|
89
90
|
|
|
91
|
+
function mergeCodexConfig(configPath: string, apiKey: string): void {
|
|
92
|
+
fs.mkdirSync(path.dirname(configPath), { recursive: true });
|
|
93
|
+
let existing = "";
|
|
94
|
+
if (fs.existsSync(configPath)) {
|
|
95
|
+
existing = fs.readFileSync(configPath, "utf8");
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
const senqBlock = `[mcp_servers.senq]\ncommand = "npx"\nargs = ["senq-mcp"]\n\n[mcp_servers.senq.env]\nSENQ_API_KEY = "${apiKey}"`;
|
|
99
|
+
|
|
100
|
+
if (existing.includes("[mcp_servers.senq]")) {
|
|
101
|
+
// Replace existing senq block
|
|
102
|
+
const updated = existing.replace(
|
|
103
|
+
/\[mcp_servers\.senq\][\s\S]*?SENQ_API_KEY\s*=\s*"[^"]*"/,
|
|
104
|
+
senqBlock,
|
|
105
|
+
);
|
|
106
|
+
fs.writeFileSync(configPath, updated);
|
|
107
|
+
} else if (existing.includes("[sandbox_workspace_write]")) {
|
|
108
|
+
// Insert before sandbox section
|
|
109
|
+
const updated = existing.replace("[sandbox_workspace_write]", `${senqBlock}\n\n[sandbox_workspace_write]`);
|
|
110
|
+
fs.writeFileSync(configPath, updated);
|
|
111
|
+
} else {
|
|
112
|
+
fs.writeFileSync(configPath, existing + (existing.endsWith("\n") || !existing ? "" : "\n") + "\n" + senqBlock + "\n");
|
|
113
|
+
}
|
|
114
|
+
}
|
|
115
|
+
|
|
90
116
|
export async function runSetup(): Promise<void> {
|
|
91
117
|
console.log("\n🤖 Настройка Senq MCP\n");
|
|
92
118
|
|
|
@@ -102,7 +128,7 @@ export async function runSetup(): Promise<void> {
|
|
|
102
128
|
const exists = fs.existsSync(c.configPath);
|
|
103
129
|
console.log(` ${i + 1}) ${c.label}${exists ? " (конфиг найден)" : ""}`);
|
|
104
130
|
});
|
|
105
|
-
console.log(` ${CLIENTS.length + 1}) Все
|
|
131
|
+
console.log(` ${CLIENTS.length + 1}) Все четыре\n`);
|
|
106
132
|
|
|
107
133
|
const choice = await ask("Введи номер [1]: ", "1");
|
|
108
134
|
const num = parseInt(choice, 10);
|
|
@@ -119,7 +145,11 @@ export async function runSetup(): Promise<void> {
|
|
|
119
145
|
console.log("");
|
|
120
146
|
for (const client of selected) {
|
|
121
147
|
try {
|
|
122
|
-
|
|
148
|
+
if (client.id === "codex") {
|
|
149
|
+
mergeCodexConfig(client.configPath, apiKey);
|
|
150
|
+
} else {
|
|
151
|
+
mergeConfig(client.configPath, apiKey);
|
|
152
|
+
}
|
|
123
153
|
console.log(` ✅ ${client.label}: ${client.configPath}`);
|
|
124
154
|
} catch (err) {
|
|
125
155
|
const msg = err instanceof Error ? err.message : String(err);
|