@chamba/mcp 0.1.0 → 0.2.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/main.js +142 -85
- package/package.json +3 -3
package/dist/main.js
CHANGED
|
@@ -147,17 +147,73 @@ function registerGeneratePlan(server, logger, services) {
|
|
|
147
147
|
);
|
|
148
148
|
}
|
|
149
149
|
|
|
150
|
+
// src/tools/get-agent-config.ts
|
|
151
|
+
import {
|
|
152
|
+
AGENT_ROLES,
|
|
153
|
+
buildHint,
|
|
154
|
+
getModel,
|
|
155
|
+
joinPath,
|
|
156
|
+
loadConfig,
|
|
157
|
+
resolveRole,
|
|
158
|
+
WORKSPACE_DIR
|
|
159
|
+
} from "@chamba/core";
|
|
160
|
+
import { z as z4 } from "zod";
|
|
161
|
+
var TOOL_NAME4 = "chamba_get_agent_config";
|
|
162
|
+
var DESCRIPTION4 = "Return the configured model + effort hint for a given agent role (orchestrator, planner, reviewer, implementer, tester, summarizer, researcher). chamba does not call any model \u2014 this is guidance the editor's own model can use to decide how to delegate. Reads ~/.chamba/config.json and ./.chamba/config.json (project overrides global); falls back to built-in defaults.";
|
|
163
|
+
var CONFIG_FILE = `${WORKSPACE_DIR}/config.json`;
|
|
164
|
+
function registerGetAgentConfig(server, logger, services) {
|
|
165
|
+
server.registerTool(
|
|
166
|
+
TOOL_NAME4,
|
|
167
|
+
{
|
|
168
|
+
title: "Get agent config",
|
|
169
|
+
description: DESCRIPTION4,
|
|
170
|
+
inputSchema: {
|
|
171
|
+
role: z4.enum([...AGENT_ROLES]).describe("The agent role to get a model + effort hint for.")
|
|
172
|
+
}
|
|
173
|
+
},
|
|
174
|
+
async ({ role }) => {
|
|
175
|
+
const globalPath = joinPath(services.homedir, CONFIG_FILE);
|
|
176
|
+
const projectPath = joinPath(services.cwd, CONFIG_FILE);
|
|
177
|
+
const { config, sources } = await loadConfig(services.fs, { globalPath, projectPath });
|
|
178
|
+
const agent = resolveRole(config, role);
|
|
179
|
+
const model = getModel(agent.model);
|
|
180
|
+
const hint = buildHint(role, agent);
|
|
181
|
+
const invalid = sources.find((s) => s.status === "invalid");
|
|
182
|
+
const warning = invalid ? `Ignored invalid config at ${invalid.path}: ${invalid.error}. Using defaults.` : void 0;
|
|
183
|
+
logger.info(
|
|
184
|
+
{ tool: TOOL_NAME4, role, model: agent.model, effort: agent.effort },
|
|
185
|
+
"get-agent-config"
|
|
186
|
+
);
|
|
187
|
+
const structured = {
|
|
188
|
+
role,
|
|
189
|
+
model: agent.model,
|
|
190
|
+
effort: agent.effort,
|
|
191
|
+
reasoning_priority: agent.reasoning_priority,
|
|
192
|
+
provider: model?.provider ?? "unknown",
|
|
193
|
+
hint,
|
|
194
|
+
...warning ? { warning } : {}
|
|
195
|
+
};
|
|
196
|
+
return {
|
|
197
|
+
content: [{ type: "text", text: warning ? `${hint}
|
|
198
|
+
|
|
199
|
+
\u26A0\uFE0F ${warning}` : hint }],
|
|
200
|
+
structuredContent: structured
|
|
201
|
+
};
|
|
202
|
+
}
|
|
203
|
+
);
|
|
204
|
+
}
|
|
205
|
+
|
|
150
206
|
// src/tools/list-worktrees.ts
|
|
151
207
|
import { WorktreeManager as WorktreeManager3 } from "@chamba/core";
|
|
152
|
-
var
|
|
153
|
-
var
|
|
208
|
+
var TOOL_NAME5 = "chamba_list_worktrees";
|
|
209
|
+
var DESCRIPTION5 = "List the git worktrees in the current repo (path, HEAD, branch).";
|
|
154
210
|
function registerListWorktrees(server, logger, services) {
|
|
155
211
|
server.registerTool(
|
|
156
|
-
|
|
157
|
-
{ title: "List worktrees", description:
|
|
212
|
+
TOOL_NAME5,
|
|
213
|
+
{ title: "List worktrees", description: DESCRIPTION5, inputSchema: {} },
|
|
158
214
|
async () => {
|
|
159
215
|
const worktrees = await new WorktreeManager3(services.process).list(services.cwd);
|
|
160
|
-
logger.info({ tool:
|
|
216
|
+
logger.info({ tool: TOOL_NAME5, count: worktrees.length }, "listed worktrees");
|
|
161
217
|
const text = worktrees.length === 0 ? "No worktrees found (or not a git repo)." : worktrees.map((w) => `- ${w.path}${w.branch ? ` [${w.branch}]` : ""}`).join("\n");
|
|
162
218
|
return {
|
|
163
219
|
content: [{ type: "text", text }],
|
|
@@ -169,18 +225,18 @@ function registerListWorktrees(server, logger, services) {
|
|
|
169
225
|
|
|
170
226
|
// src/tools/load-context.ts
|
|
171
227
|
import { ContextBuilder, ObsidianDetector, WorkspaceScanner as WorkspaceScanner2 } from "@chamba/core";
|
|
172
|
-
import { z as
|
|
173
|
-
var
|
|
174
|
-
var
|
|
228
|
+
import { z as z5 } from "zod";
|
|
229
|
+
var TOOL_NAME6 = "chamba_load_context";
|
|
230
|
+
var DESCRIPTION6 = "Load context for a task: a summary of the workspace plus, when an Obsidian vault is available, the notes most relevant to the task (keyword search). Returns a markdown block the model can reason over before planning.";
|
|
175
231
|
function registerLoadContext(server, logger, services) {
|
|
176
232
|
server.registerTool(
|
|
177
|
-
|
|
233
|
+
TOOL_NAME6,
|
|
178
234
|
{
|
|
179
235
|
title: "Load context",
|
|
180
|
-
description:
|
|
236
|
+
description: DESCRIPTION6,
|
|
181
237
|
inputSchema: {
|
|
182
|
-
task:
|
|
183
|
-
includeObsidian:
|
|
238
|
+
task: z5.string().describe("The task you are about to work on."),
|
|
239
|
+
includeObsidian: z5.boolean().optional().describe("Search the Obsidian vault for relevant notes (default true).")
|
|
184
240
|
}
|
|
185
241
|
},
|
|
186
242
|
async ({ task, includeObsidian }) => {
|
|
@@ -195,7 +251,7 @@ function registerLoadContext(server, logger, services) {
|
|
|
195
251
|
}
|
|
196
252
|
const built = await new ContextBuilder(services.fs).build({ workspace, task, vaultPath });
|
|
197
253
|
logger.info(
|
|
198
|
-
{ tool:
|
|
254
|
+
{ tool: TOOL_NAME6, vault: vaultPath ?? null, notes: built.relevantNotes.length },
|
|
199
255
|
"context built"
|
|
200
256
|
);
|
|
201
257
|
return { content: [{ type: "text", text: built.context }] };
|
|
@@ -205,23 +261,23 @@ function registerLoadContext(server, logger, services) {
|
|
|
205
261
|
|
|
206
262
|
// src/tools/recall.ts
|
|
207
263
|
import { FilesystemMemoryStore } from "@chamba/core";
|
|
208
|
-
import { z as
|
|
209
|
-
var
|
|
210
|
-
var
|
|
264
|
+
import { z as z6 } from "zod";
|
|
265
|
+
var TOOL_NAME7 = "chamba_recall";
|
|
266
|
+
var DESCRIPTION7 = "Search persisted memories (case-insensitive substring over key, tags and content) and return the matches with their paths and content.";
|
|
211
267
|
function registerRecall(server, logger, services) {
|
|
212
268
|
server.registerTool(
|
|
213
|
-
|
|
269
|
+
TOOL_NAME7,
|
|
214
270
|
{
|
|
215
271
|
title: "Recall",
|
|
216
|
-
description:
|
|
272
|
+
description: DESCRIPTION7,
|
|
217
273
|
inputSchema: {
|
|
218
|
-
query:
|
|
274
|
+
query: z6.string().describe("Keywords to search for.")
|
|
219
275
|
}
|
|
220
276
|
},
|
|
221
277
|
async ({ query }) => {
|
|
222
278
|
const store = new FilesystemMemoryStore(services.fs, services.clock, services.cwd);
|
|
223
279
|
const matches = await store.recall(query);
|
|
224
|
-
logger.info({ tool:
|
|
280
|
+
logger.info({ tool: TOOL_NAME7, query, matches: matches.length }, "recall");
|
|
225
281
|
const text = matches.length === 0 ? `No memories matched "${query}".` : matches.map((m) => `### ${m.key} (\`${m.path}\`)
|
|
226
282
|
${m.content}`).join("\n\n");
|
|
227
283
|
return {
|
|
@@ -241,25 +297,25 @@ ${m.content}`).join("\n\n");
|
|
|
241
297
|
|
|
242
298
|
// src/tools/remember.ts
|
|
243
299
|
import { FilesystemMemoryStore as FilesystemMemoryStore2 } from "@chamba/core";
|
|
244
|
-
import { z as
|
|
245
|
-
var
|
|
246
|
-
var
|
|
300
|
+
import { z as z7 } from "zod";
|
|
301
|
+
var TOOL_NAME8 = "chamba_remember";
|
|
302
|
+
var DESCRIPTION8 = "Persist a piece of knowledge across sessions as an editable markdown file under `.chamba/memory/<key>.md`. Re-remembering an existing key appends a timestamped section instead of overwriting.";
|
|
247
303
|
function registerRemember(server, logger, services) {
|
|
248
304
|
server.registerTool(
|
|
249
|
-
|
|
305
|
+
TOOL_NAME8,
|
|
250
306
|
{
|
|
251
307
|
title: "Remember",
|
|
252
|
-
description:
|
|
308
|
+
description: DESCRIPTION8,
|
|
253
309
|
inputSchema: {
|
|
254
|
-
key:
|
|
255
|
-
content:
|
|
256
|
-
tags:
|
|
310
|
+
key: z7.string().describe('Short identifier, e.g. "auth-decisions".'),
|
|
311
|
+
content: z7.string().describe("What to remember (markdown)."),
|
|
312
|
+
tags: z7.array(z7.string()).optional().describe("Optional tags for search.")
|
|
257
313
|
}
|
|
258
314
|
},
|
|
259
315
|
async ({ key, content, tags }) => {
|
|
260
316
|
const store = new FilesystemMemoryStore2(services.fs, services.clock, services.cwd);
|
|
261
317
|
const memory = await store.remember({ key, content, tags });
|
|
262
|
-
logger.info({ tool:
|
|
318
|
+
logger.info({ tool: TOOL_NAME8, key, path: memory.path }, "memory saved");
|
|
263
319
|
return {
|
|
264
320
|
content: [{ type: "text", text: `Saved memory '${key}' to ${memory.path}` }],
|
|
265
321
|
structuredContent: { saved: true, path: memory.path }
|
|
@@ -270,38 +326,38 @@ function registerRemember(server, logger, services) {
|
|
|
270
326
|
|
|
271
327
|
// src/tools/review-plan.ts
|
|
272
328
|
import { Reviewer, WorkspaceScanner as WorkspaceScanner3 } from "@chamba/core";
|
|
273
|
-
import { z as
|
|
274
|
-
var
|
|
275
|
-
var
|
|
329
|
+
import { z as z8 } from "zod";
|
|
330
|
+
var TOOL_NAME9 = "chamba_review_plan";
|
|
331
|
+
var DESCRIPTION9 = "Review a plan with programmatic heuristics (NO LLM): checks for acceptance criteria, tests, subtasks with assigned workers, concrete descriptions, files outside the workspace, and risk assessment for sensitive areas. Returns { approved, issues, suggestions, riskFlags }.";
|
|
276
332
|
function registerReviewPlan(server, logger, services) {
|
|
277
333
|
server.registerTool(
|
|
278
|
-
|
|
334
|
+
TOOL_NAME9,
|
|
279
335
|
{
|
|
280
336
|
title: "Review plan",
|
|
281
|
-
description:
|
|
337
|
+
description: DESCRIPTION9,
|
|
282
338
|
inputSchema: {
|
|
283
|
-
plan:
|
|
284
|
-
task:
|
|
285
|
-
context:
|
|
339
|
+
plan: z8.string().describe("The plan markdown to review."),
|
|
340
|
+
task: z8.string().describe("The task the plan is for."),
|
|
341
|
+
context: z8.string().optional().describe("Context from chamba_load_context, if any.")
|
|
286
342
|
},
|
|
287
343
|
outputSchema: {
|
|
288
|
-
approved:
|
|
289
|
-
issues:
|
|
290
|
-
|
|
291
|
-
code:
|
|
292
|
-
severity:
|
|
293
|
-
message:
|
|
344
|
+
approved: z8.boolean(),
|
|
345
|
+
issues: z8.array(
|
|
346
|
+
z8.object({
|
|
347
|
+
code: z8.string(),
|
|
348
|
+
severity: z8.enum(["error", "warning"]),
|
|
349
|
+
message: z8.string()
|
|
294
350
|
})
|
|
295
351
|
),
|
|
296
|
-
suggestions:
|
|
297
|
-
riskFlags:
|
|
352
|
+
suggestions: z8.array(z8.string()),
|
|
353
|
+
riskFlags: z8.array(z8.string())
|
|
298
354
|
}
|
|
299
355
|
},
|
|
300
356
|
async ({ plan, task, context }) => {
|
|
301
357
|
const workspace = await new WorkspaceScanner3(services.fs).scan(services.cwd);
|
|
302
358
|
const review = new Reviewer().review({ plan, task, context, workspace });
|
|
303
359
|
logger.info(
|
|
304
|
-
{ tool:
|
|
360
|
+
{ tool: TOOL_NAME9, approved: review.approved, issues: review.issues.length },
|
|
305
361
|
"plan reviewed"
|
|
306
362
|
);
|
|
307
363
|
const verdict = review.approved ? "\u2705 approved" : "\u274C changes requested";
|
|
@@ -326,20 +382,20 @@ ${review.suggestions.map((s) => `- ${s}`).join("\n")}` : ""
|
|
|
326
382
|
|
|
327
383
|
// src/tools/summarize-to-vault.ts
|
|
328
384
|
import { ObsidianDetector as ObsidianDetector2, VaultWriter } from "@chamba/core";
|
|
329
|
-
import { z as
|
|
330
|
-
var
|
|
385
|
+
import { z as z9 } from "zod";
|
|
386
|
+
var TOOL_NAME10 = "chamba_summarize_to_vault";
|
|
331
387
|
var NO_VAULT_ERROR = "No Obsidian vault configured. Set CHAMBA_OBSIDIAN_VAULT_PATH or use the obsidian-mcp server";
|
|
332
|
-
var
|
|
388
|
+
var DESCRIPTION10 = "Write a structured summary note to the Obsidian vault under `proyectos/<date>-<slug>.md` with valid YAML frontmatter. Fails clearly if no vault is configured.";
|
|
333
389
|
function registerSummarizeToVault(server, logger, services) {
|
|
334
390
|
server.registerTool(
|
|
335
|
-
|
|
391
|
+
TOOL_NAME10,
|
|
336
392
|
{
|
|
337
393
|
title: "Summarize to vault",
|
|
338
|
-
description:
|
|
394
|
+
description: DESCRIPTION10,
|
|
339
395
|
inputSchema: {
|
|
340
|
-
title:
|
|
341
|
-
content:
|
|
342
|
-
projectSlug:
|
|
396
|
+
title: z9.string().describe("Note title."),
|
|
397
|
+
content: z9.string().describe("Markdown body (summary, plan, decisions, next steps)."),
|
|
398
|
+
projectSlug: z9.string().optional().describe("Optional slug for the filename.")
|
|
343
399
|
}
|
|
344
400
|
},
|
|
345
401
|
async ({ title, content, projectSlug }) => {
|
|
@@ -348,7 +404,7 @@ function registerSummarizeToVault(server, logger, services) {
|
|
|
348
404
|
searchRoots: obsidianSearchRoots(services)
|
|
349
405
|
});
|
|
350
406
|
if (!detection.found || !detection.path) {
|
|
351
|
-
logger.info({ tool:
|
|
407
|
+
logger.info({ tool: TOOL_NAME10 }, "no vault configured");
|
|
352
408
|
return { isError: true, content: [{ type: "text", text: NO_VAULT_ERROR }] };
|
|
353
409
|
}
|
|
354
410
|
const writer = new VaultWriter(services.fs, services.clock);
|
|
@@ -358,7 +414,7 @@ function registerSummarizeToVault(server, logger, services) {
|
|
|
358
414
|
content,
|
|
359
415
|
projectSlug
|
|
360
416
|
});
|
|
361
|
-
logger.info({ tool:
|
|
417
|
+
logger.info({ tool: TOOL_NAME10, notePath }, "note written to vault");
|
|
362
418
|
return { content: [{ type: "text", text: `Wrote note to ${notePath}` }] };
|
|
363
419
|
}
|
|
364
420
|
);
|
|
@@ -366,31 +422,31 @@ function registerSummarizeToVault(server, logger, services) {
|
|
|
366
422
|
|
|
367
423
|
// src/tools/workspace-init.ts
|
|
368
424
|
import {
|
|
369
|
-
joinPath,
|
|
425
|
+
joinPath as joinPath2,
|
|
370
426
|
renderWorkspaceMarkdown,
|
|
371
|
-
WORKSPACE_DIR,
|
|
427
|
+
WORKSPACE_DIR as WORKSPACE_DIR2,
|
|
372
428
|
WORKSPACE_RELATIVE_PATH,
|
|
373
429
|
WorkspaceScanner as WorkspaceScanner4
|
|
374
430
|
} from "@chamba/core";
|
|
375
|
-
import { z as
|
|
376
|
-
var
|
|
377
|
-
var
|
|
431
|
+
import { z as z10 } from "zod";
|
|
432
|
+
var TOOL_NAME11 = "chamba_workspace_init";
|
|
433
|
+
var DESCRIPTION11 = "Scan the workspace and generate `.chamba/workspace.md` (description, languages, framework, conventions, active projects, folder map). Respects .gitignore/.dockerignore and never reads node_modules or binaries. If the file already exists it is NOT overwritten \u2014 its current contents are returned so the model/user decides what to do.";
|
|
378
434
|
function registerWorkspaceInit(server, logger, services) {
|
|
379
435
|
server.registerTool(
|
|
380
|
-
|
|
436
|
+
TOOL_NAME11,
|
|
381
437
|
{
|
|
382
438
|
title: "Init workspace",
|
|
383
|
-
description:
|
|
439
|
+
description: DESCRIPTION11,
|
|
384
440
|
inputSchema: {
|
|
385
|
-
root:
|
|
441
|
+
root: z10.string().optional().describe("Workspace root to scan. Defaults to the directory chamba runs in.")
|
|
386
442
|
}
|
|
387
443
|
},
|
|
388
444
|
async ({ root }) => {
|
|
389
445
|
const workspaceRoot = root ?? services.cwd;
|
|
390
|
-
const wsPath =
|
|
446
|
+
const wsPath = joinPath2(workspaceRoot, WORKSPACE_RELATIVE_PATH);
|
|
391
447
|
if (await services.fs.exists(wsPath)) {
|
|
392
448
|
const currentContents = await services.fs.readFile(wsPath);
|
|
393
|
-
logger.info({ tool:
|
|
449
|
+
logger.info({ tool: TOOL_NAME11, wsPath }, "workspace.md already exists, not overwriting");
|
|
394
450
|
return {
|
|
395
451
|
content: [
|
|
396
452
|
{
|
|
@@ -407,10 +463,10 @@ ${currentContents}`
|
|
|
407
463
|
const scanner = new WorkspaceScanner4(services.fs);
|
|
408
464
|
const workspace = await scanner.scan(workspaceRoot);
|
|
409
465
|
const markdown = renderWorkspaceMarkdown(workspace);
|
|
410
|
-
await services.fs.mkdir(
|
|
466
|
+
await services.fs.mkdir(joinPath2(workspaceRoot, WORKSPACE_DIR2));
|
|
411
467
|
await services.fs.writeFile(wsPath, markdown);
|
|
412
468
|
logger.info(
|
|
413
|
-
{ tool:
|
|
469
|
+
{ tool: TOOL_NAME11, wsPath, projects: workspace.projects.length },
|
|
414
470
|
"workspace.md created"
|
|
415
471
|
);
|
|
416
472
|
return {
|
|
@@ -430,26 +486,26 @@ ${markdown}`
|
|
|
430
486
|
// src/tools/workspace-reload.ts
|
|
431
487
|
import {
|
|
432
488
|
diffLines,
|
|
433
|
-
joinPath as
|
|
489
|
+
joinPath as joinPath3,
|
|
434
490
|
renderWorkspaceMarkdown as renderWorkspaceMarkdown2,
|
|
435
491
|
textsEqual,
|
|
436
492
|
WORKSPACE_RELATIVE_PATH as WORKSPACE_RELATIVE_PATH2,
|
|
437
493
|
WorkspaceScanner as WorkspaceScanner5
|
|
438
494
|
} from "@chamba/core";
|
|
439
|
-
var
|
|
440
|
-
var
|
|
495
|
+
var TOOL_NAME12 = "chamba_workspace_reload";
|
|
496
|
+
var DESCRIPTION12 = "Re-scan the workspace and return a diff against the current `.chamba/workspace.md`. NEVER overwrites the file \u2014 the user may have hand-edited it. The model decides whether to apply changes.";
|
|
441
497
|
function registerWorkspaceReload(server, logger, services) {
|
|
442
498
|
server.registerTool(
|
|
443
|
-
|
|
499
|
+
TOOL_NAME12,
|
|
444
500
|
{
|
|
445
501
|
title: "Reload workspace",
|
|
446
|
-
description:
|
|
502
|
+
description: DESCRIPTION12,
|
|
447
503
|
inputSchema: {}
|
|
448
504
|
},
|
|
449
505
|
async () => {
|
|
450
|
-
const wsPath =
|
|
506
|
+
const wsPath = joinPath3(services.cwd, WORKSPACE_RELATIVE_PATH2);
|
|
451
507
|
if (!await services.fs.exists(wsPath)) {
|
|
452
|
-
logger.info({ tool:
|
|
508
|
+
logger.info({ tool: TOOL_NAME12, wsPath }, "no workspace.md to reload");
|
|
453
509
|
return {
|
|
454
510
|
content: [
|
|
455
511
|
{
|
|
@@ -463,7 +519,7 @@ function registerWorkspaceReload(server, logger, services) {
|
|
|
463
519
|
const scanner = new WorkspaceScanner5(services.fs);
|
|
464
520
|
const rescanned = renderWorkspaceMarkdown2(await scanner.scan(services.cwd));
|
|
465
521
|
if (textsEqual(current, rescanned)) {
|
|
466
|
-
logger.info({ tool:
|
|
522
|
+
logger.info({ tool: TOOL_NAME12, wsPath }, "workspace.md up to date");
|
|
467
523
|
return {
|
|
468
524
|
content: [
|
|
469
525
|
{
|
|
@@ -473,7 +529,7 @@ function registerWorkspaceReload(server, logger, services) {
|
|
|
473
529
|
]
|
|
474
530
|
};
|
|
475
531
|
}
|
|
476
|
-
logger.info({ tool:
|
|
532
|
+
logger.info({ tool: TOOL_NAME12, wsPath }, "workspace.md differs from re-scan");
|
|
477
533
|
return {
|
|
478
534
|
content: [
|
|
479
535
|
{
|
|
@@ -491,25 +547,25 @@ ${diffLines(current, rescanned)}
|
|
|
491
547
|
}
|
|
492
548
|
|
|
493
549
|
// src/tools/workspace-show.ts
|
|
494
|
-
import { joinPath as
|
|
495
|
-
var
|
|
496
|
-
var
|
|
550
|
+
import { joinPath as joinPath4, WORKSPACE_RELATIVE_PATH as WORKSPACE_RELATIVE_PATH3 } from "@chamba/core";
|
|
551
|
+
var TOOL_NAME13 = "chamba_workspace_show";
|
|
552
|
+
var DESCRIPTION13 = "Show the current workspace map. Reads `.chamba/workspace.md` from the workspace root and returns its contents. If no workspace file exists yet, says so \u2014 the model can then run chamba_workspace_init to create one.";
|
|
497
553
|
function registerWorkspaceShow(server, logger, services) {
|
|
498
554
|
server.registerTool(
|
|
499
|
-
|
|
555
|
+
TOOL_NAME13,
|
|
500
556
|
{
|
|
501
557
|
title: "Show workspace",
|
|
502
|
-
description:
|
|
558
|
+
description: DESCRIPTION13,
|
|
503
559
|
inputSchema: {}
|
|
504
560
|
},
|
|
505
561
|
async () => {
|
|
506
|
-
const path =
|
|
562
|
+
const path = joinPath4(services.cwd, WORKSPACE_RELATIVE_PATH3);
|
|
507
563
|
try {
|
|
508
564
|
const contents = await services.fs.readFile(path);
|
|
509
|
-
logger.info({ tool:
|
|
565
|
+
logger.info({ tool: TOOL_NAME13, path }, "workspace.md read");
|
|
510
566
|
return { content: [{ type: "text", text: contents }] };
|
|
511
567
|
} catch {
|
|
512
|
-
logger.info({ tool:
|
|
568
|
+
logger.info({ tool: TOOL_NAME13, path }, "no workspace.md found");
|
|
513
569
|
return {
|
|
514
570
|
content: [
|
|
515
571
|
{
|
|
@@ -540,6 +596,7 @@ function createServer(logger, services = createNodeServices()) {
|
|
|
540
596
|
registerCleanupWorktree(server, logger, services);
|
|
541
597
|
registerRemember(server, logger, services);
|
|
542
598
|
registerRecall(server, logger, services);
|
|
599
|
+
registerGetAgentConfig(server, logger, services);
|
|
543
600
|
return server;
|
|
544
601
|
}
|
|
545
602
|
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@chamba/mcp",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.2.0",
|
|
4
4
|
"description": "chamba MCP server — orchestration, workspace, worktree and Obsidian tools for any MCP-capable editor",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"type": "module",
|
|
@@ -36,8 +36,8 @@
|
|
|
36
36
|
"@modelcontextprotocol/sdk": "^1.12.0",
|
|
37
37
|
"pino": "^9.0.0",
|
|
38
38
|
"zod": "^3.23.0",
|
|
39
|
-
"@chamba/
|
|
40
|
-
"@chamba/
|
|
39
|
+
"@chamba/adapters": "0.2.0",
|
|
40
|
+
"@chamba/core": "0.2.0"
|
|
41
41
|
},
|
|
42
42
|
"devDependencies": {
|
|
43
43
|
"@types/node": "^22.0.0",
|