@arcbridge/mcp-server 0.2.1 → 0.3.1
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 +12 -3
- package/dist/index.js +112 -7
- package/dist/index.js.map +1 -1
- package/package.json +3 -3
package/README.md
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
# @arcbridge/mcp-server
|
|
2
2
|
|
|
3
|
-
MCP server for ArcBridge — exposes
|
|
3
|
+
MCP server for ArcBridge — exposes 34 architecture tools to AI coding agents via the [Model Context Protocol](https://modelcontextprotocol.io).
|
|
4
4
|
|
|
5
5
|
## Install
|
|
6
6
|
|
|
@@ -10,7 +10,7 @@ npm install -g @arcbridge/mcp-server
|
|
|
10
10
|
|
|
11
11
|
## Setup
|
|
12
12
|
|
|
13
|
-
|
|
13
|
+
**Claude Code** — add to your project's `.mcp.json`:
|
|
14
14
|
|
|
15
15
|
```json
|
|
16
16
|
{
|
|
@@ -23,7 +23,15 @@ Add to your project's `.mcp.json`:
|
|
|
23
23
|
}
|
|
24
24
|
```
|
|
25
25
|
|
|
26
|
-
|
|
26
|
+
**Codex CLI** — add to `~/.codex/config.toml`:
|
|
27
|
+
|
|
28
|
+
```toml
|
|
29
|
+
[mcp_servers.arcbridge]
|
|
30
|
+
command = "npx"
|
|
31
|
+
args = ["-y", "@arcbridge/mcp-server"]
|
|
32
|
+
```
|
|
33
|
+
|
|
34
|
+
Restart your AI agent and approve the MCP server when prompted.
|
|
27
35
|
|
|
28
36
|
## Tools
|
|
29
37
|
|
|
@@ -81,6 +89,7 @@ Restart your AI agent (Claude Code, etc.) and approve the MCP server when prompt
|
|
|
81
89
|
| `arcbridge_get_open_questions` | Unresolved architectural questions and risks |
|
|
82
90
|
| `arcbridge_propose_arc42_update` | Generate arc42 update proposals from code changes |
|
|
83
91
|
| `arcbridge_get_practice_review` | 5-dimension review: architecture, security, testing, docs, complexity |
|
|
92
|
+
| `arcbridge_update_arc42_section` | Read or update any arc42 markdown section (frontmatter preserved) |
|
|
84
93
|
|
|
85
94
|
### Roles & Sync
|
|
86
95
|
|
package/dist/index.js
CHANGED
|
@@ -31,7 +31,9 @@ import {
|
|
|
31
31
|
generateDatabase,
|
|
32
32
|
generateSyncFiles,
|
|
33
33
|
indexProject,
|
|
34
|
-
loadConfig
|
|
34
|
+
loadConfig,
|
|
35
|
+
QualityCategorySchema,
|
|
36
|
+
QUALITY_PRIORITIES_DESCRIPTION
|
|
35
37
|
} from "@arcbridge/core";
|
|
36
38
|
import { getAdapter } from "@arcbridge/adapters";
|
|
37
39
|
function registerInitProject(server, ctx) {
|
|
@@ -44,7 +46,7 @@ function registerInitProject(server, ctx) {
|
|
|
44
46
|
"Project template: nextjs-app-router (Next.js with App Router, SSR/SSG), react-vite (React SPA with Vite, client-only), api-service (Node.js API with Express/Fastify/Hono), dotnet-webapi (ASP.NET Core Web API, C#), unity-game (Unity game project, C#, code-heavy)"
|
|
45
47
|
),
|
|
46
48
|
features: z.array(z.enum(["auth", "database", "api"])).default([]).describe("Features to scaffold"),
|
|
47
|
-
quality_priorities: z.array(
|
|
49
|
+
quality_priorities: z.array(QualityCategorySchema).default(["security", "performance", "accessibility", "maintainability"]).describe(QUALITY_PRIORITIES_DESCRIPTION),
|
|
48
50
|
platforms: z.array(z.string()).default(["claude"]).describe("Target platforms for agent config generation"),
|
|
49
51
|
target_dir: z.string().describe("Absolute path to the target project directory"),
|
|
50
52
|
spec: z.string().optional().describe(
|
|
@@ -568,14 +570,14 @@ function registerGetBuildingBlock(server, ctx) {
|
|
|
568
570
|
|
|
569
571
|
// src/tools/get-quality-scenarios.ts
|
|
570
572
|
import { z as z5 } from "zod";
|
|
571
|
-
import { QualityCategorySchema, QualityPrioritySchema, QualityScenarioStatusSchema } from "@arcbridge/core";
|
|
573
|
+
import { QualityCategorySchema as QualityCategorySchema2, QualityPrioritySchema, QualityScenarioStatusSchema } from "@arcbridge/core";
|
|
572
574
|
function registerGetQualityScenarios(server, ctx) {
|
|
573
575
|
server.tool(
|
|
574
576
|
"arcbridge_get_quality_scenarios",
|
|
575
577
|
"Get quality scenarios, optionally filtered by category. Shows scenario details, linked code/tests, and current status.",
|
|
576
578
|
{
|
|
577
579
|
target_dir: z5.string().describe("Absolute path to the project directory"),
|
|
578
|
-
category:
|
|
580
|
+
category: QualityCategorySchema2.optional().describe("Filter by category"),
|
|
579
581
|
status: QualityScenarioStatusSchema.optional().describe("Filter by status"),
|
|
580
582
|
priority: QualityPrioritySchema.optional().describe("Filter by priority (must/should/could)")
|
|
581
583
|
},
|
|
@@ -756,7 +758,7 @@ import { refreshFromDocs as refreshFromDocs3 } from "@arcbridge/core";
|
|
|
756
758
|
function registerGetCurrentTasks(server, ctx) {
|
|
757
759
|
server.tool(
|
|
758
760
|
"arcbridge_get_current_tasks",
|
|
759
|
-
"Get tasks for the current in-progress
|
|
761
|
+
"Get tasks for the current phase (in-progress, or first planned if none is in-progress), with their building blocks, quality scenarios, and acceptance criteria.",
|
|
760
762
|
{
|
|
761
763
|
target_dir: z7.string().describe("Absolute path to the project directory"),
|
|
762
764
|
status: z7.enum(["todo", "in-progress", "done", "blocked"]).optional().describe("Filter tasks by status")
|
|
@@ -765,15 +767,20 @@ function registerGetCurrentTasks(server, ctx) {
|
|
|
765
767
|
const db = ensureDb(ctx, params.target_dir);
|
|
766
768
|
if (!db) return notInitialized();
|
|
767
769
|
refreshFromDocs3(db, params.target_dir);
|
|
768
|
-
|
|
770
|
+
let currentPhase = db.prepare(
|
|
769
771
|
"SELECT id, name FROM phases WHERE status = 'in-progress' ORDER BY phase_number LIMIT 1"
|
|
770
772
|
).get();
|
|
773
|
+
if (!currentPhase) {
|
|
774
|
+
currentPhase = db.prepare(
|
|
775
|
+
"SELECT id, name FROM phases WHERE status = 'planned' ORDER BY phase_number LIMIT 1"
|
|
776
|
+
).get();
|
|
777
|
+
}
|
|
771
778
|
if (!currentPhase) {
|
|
772
779
|
return {
|
|
773
780
|
content: [
|
|
774
781
|
{
|
|
775
782
|
type: "text",
|
|
776
|
-
text: "No
|
|
783
|
+
text: "No active or planned phases found. Use `arcbridge_get_phase_plan` to see all phases."
|
|
777
784
|
}
|
|
778
785
|
]
|
|
779
786
|
};
|
|
@@ -4395,6 +4402,103 @@ You can commit this file to preserve the activity record in git.`
|
|
|
4395
4402
|
);
|
|
4396
4403
|
}
|
|
4397
4404
|
|
|
4405
|
+
// src/tools/update-arc42-section.ts
|
|
4406
|
+
import { z as z34 } from "zod";
|
|
4407
|
+
import { join as join4 } from "path";
|
|
4408
|
+
import { existsSync as existsSync4, readFileSync as readFileSync2, writeFileSync as writeFileSync2 } from "fs";
|
|
4409
|
+
function splitFrontmatter(raw) {
|
|
4410
|
+
if (!raw.startsWith("---")) {
|
|
4411
|
+
return { frontmatterBlock: "", body: raw };
|
|
4412
|
+
}
|
|
4413
|
+
const endIndex = raw.indexOf("\n---", 3);
|
|
4414
|
+
if (endIndex < 0) {
|
|
4415
|
+
return { frontmatterBlock: "", body: raw };
|
|
4416
|
+
}
|
|
4417
|
+
const fmEnd = endIndex + 4;
|
|
4418
|
+
return {
|
|
4419
|
+
frontmatterBlock: raw.slice(0, fmEnd),
|
|
4420
|
+
body: raw.slice(fmEnd).replace(/^\n/, "")
|
|
4421
|
+
};
|
|
4422
|
+
}
|
|
4423
|
+
var VALID_SECTIONS = [
|
|
4424
|
+
"01-introduction",
|
|
4425
|
+
"02-constraints",
|
|
4426
|
+
"03-context",
|
|
4427
|
+
"04-solution-strategy",
|
|
4428
|
+
"06-runtime-views",
|
|
4429
|
+
"07-deployment",
|
|
4430
|
+
"08-crosscutting",
|
|
4431
|
+
"11-risks-debt"
|
|
4432
|
+
];
|
|
4433
|
+
var SECTION_LABELS = {
|
|
4434
|
+
"01-introduction": "Introduction & Goals",
|
|
4435
|
+
"02-constraints": "Architecture Constraints",
|
|
4436
|
+
"03-context": "Context & Scope",
|
|
4437
|
+
"04-solution-strategy": "Solution Strategy",
|
|
4438
|
+
"06-runtime-views": "Runtime Views",
|
|
4439
|
+
"07-deployment": "Deployment View",
|
|
4440
|
+
"08-crosscutting": "Crosscutting Concepts",
|
|
4441
|
+
"11-risks-debt": "Risks & Technical Debt"
|
|
4442
|
+
};
|
|
4443
|
+
function registerUpdateArc42Section(server, ctx) {
|
|
4444
|
+
server.tool(
|
|
4445
|
+
"arcbridge_update_arc42_section",
|
|
4446
|
+
"Read or update an arc42 documentation section. Omit `content` to read the current section. Provide `content` to replace the markdown body (frontmatter is preserved automatically). Use this for sections without dedicated tools: introduction, constraints, context, solution strategy, runtime views, deployment, crosscutting concepts, risks & debt. For building blocks use `arcbridge_get_building_blocks`, for quality scenarios use `arcbridge_get_quality_scenarios`.",
|
|
4447
|
+
{
|
|
4448
|
+
target_dir: z34.string().describe("Absolute path to the project directory"),
|
|
4449
|
+
section: z34.enum(VALID_SECTIONS).describe(
|
|
4450
|
+
"Arc42 section to read or update: " + VALID_SECTIONS.map((s) => `${s} (${SECTION_LABELS[s]})`).join(", ")
|
|
4451
|
+
),
|
|
4452
|
+
content: z34.string().optional().describe(
|
|
4453
|
+
"New markdown content for the section body. Omit to read the current content. Frontmatter is preserved automatically \u2014 only provide the markdown body."
|
|
4454
|
+
)
|
|
4455
|
+
},
|
|
4456
|
+
async (params) => {
|
|
4457
|
+
const db = ensureDb(ctx, params.target_dir);
|
|
4458
|
+
if (!db) return notInitialized();
|
|
4459
|
+
const filePath = join4(
|
|
4460
|
+
params.target_dir,
|
|
4461
|
+
".arcbridge",
|
|
4462
|
+
"arc42",
|
|
4463
|
+
`${params.section}.md`
|
|
4464
|
+
);
|
|
4465
|
+
if (!existsSync4(filePath)) {
|
|
4466
|
+
return textResult(
|
|
4467
|
+
`Section file \`${params.section}.md\` not found. Run \`arcbridge_init_project\` first.`
|
|
4468
|
+
);
|
|
4469
|
+
}
|
|
4470
|
+
if (params.content === void 0) {
|
|
4471
|
+
const raw2 = readFileSync2(filePath, "utf-8");
|
|
4472
|
+
const { body } = splitFrontmatter(raw2);
|
|
4473
|
+
const label2 = SECTION_LABELS[params.section];
|
|
4474
|
+
const trimmedBody = body.trim();
|
|
4475
|
+
const startsWithHeading = /^#\s+/.test(trimmedBody);
|
|
4476
|
+
const outputLines = [];
|
|
4477
|
+
if (!startsWithHeading) {
|
|
4478
|
+
outputLines.push(`# ${label2}`, "");
|
|
4479
|
+
}
|
|
4480
|
+
outputLines.push(
|
|
4481
|
+
`**File:** \`.arcbridge/arc42/${params.section}.md\``,
|
|
4482
|
+
"",
|
|
4483
|
+
trimmedBody
|
|
4484
|
+
);
|
|
4485
|
+
return textResult(outputLines.join("\n"));
|
|
4486
|
+
}
|
|
4487
|
+
const raw = readFileSync2(filePath, "utf-8");
|
|
4488
|
+
const { frontmatterBlock } = splitFrontmatter(raw);
|
|
4489
|
+
const updated = frontmatterBlock ? `${frontmatterBlock}
|
|
4490
|
+
${params.content}
|
|
4491
|
+
` : `${params.content}
|
|
4492
|
+
`;
|
|
4493
|
+
writeFileSync2(filePath, updated, "utf-8");
|
|
4494
|
+
const label = SECTION_LABELS[params.section];
|
|
4495
|
+
return textResult(
|
|
4496
|
+
`Updated **${label}** (\`${params.section}.md\`). Frontmatter preserved.`
|
|
4497
|
+
);
|
|
4498
|
+
}
|
|
4499
|
+
);
|
|
4500
|
+
}
|
|
4501
|
+
|
|
4398
4502
|
// src/server.ts
|
|
4399
4503
|
var require2 = createRequire(import.meta.url);
|
|
4400
4504
|
var { version } = require2("../package.json");
|
|
@@ -4434,6 +4538,7 @@ function createArcBridgeServer() {
|
|
|
4434
4538
|
registerVerifyScenarios(server, ctx);
|
|
4435
4539
|
registerUpdateScenarioStatus(server, ctx);
|
|
4436
4540
|
registerRunRoleCheck(server, ctx);
|
|
4541
|
+
registerUpdateArc42Section(server, ctx);
|
|
4437
4542
|
registerRecordActivity(server, ctx);
|
|
4438
4543
|
registerGetMetrics(server, ctx);
|
|
4439
4544
|
registerExportMetrics(server, ctx);
|