@elixium.ai/mcp-server 0.1.6 → 0.1.8

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/LICENSE ADDED
@@ -0,0 +1 @@
1
+ Copyright (c) 2026 IndirectTek. All rights reserved.
package/README.md CHANGED
@@ -42,7 +42,8 @@ Add the following to your IDE's MCP configuration file (e.g., `mcp_config.json`)
42
42
  "env": {
43
43
  "ELIXIUM_API_KEY": "<YOUR_API_KEY>",
44
44
  "ELIXIUM_API_URL": "https://<YOUR_TENANT>.elixium.ai/api",
45
- "ELIXIUM_BOARD_SLUG": "main"
45
+ "ELIXIUM_BOARD_SLUG": "main",
46
+ "ELIXIUM_USER_EMAIL": "<YOUR_EMAIL>"
46
47
  }
47
48
  }
48
49
  }
@@ -52,6 +53,7 @@ Add the following to your IDE's MCP configuration file (e.g., `mcp_config.json`)
52
53
  Replace:
53
54
  - `<YOUR_API_KEY>` with the API key from your administrator
54
55
  - `<YOUR_TENANT>` with your workspace subdomain (e.g., `acme` for `acme.elixium.ai`)
56
+ - `<YOUR_EMAIL>` with your email address (used as the "requester" on stories you create)
55
57
 
56
58
  > [!NOTE]
57
59
  > Different IDEs and MCP clients expect different top-level keys and file paths.
@@ -116,6 +118,7 @@ If you're using multiple MCP servers, combine them in the same config:
116
118
  | `ELIXIUM_API_KEY` | ✅ Yes | Your tenant-scoped API key |
117
119
  | `ELIXIUM_API_URL` | ✅ Yes | Your tenant's API endpoint (e.g., `https://acme.elixium.ai/api`) |
118
120
  | `ELIXIUM_BOARD_SLUG` | ⚠️ Recommended | Board slug to scope operations (e.g., `main`) |
121
+ | `ELIXIUM_USER_EMAIL` | Optional | Your email address. Sets the "Requested by" field when creating stories. Defaults to API key owner. |
119
122
  | `ELIXIUM_LANE_STYLE` | Optional | `upper` for `BACKLOG/CURRENT` or `title` for `Backlog/Current` (auto-detected) |
120
123
 
121
124
  > [!IMPORTANT]
@@ -130,6 +133,39 @@ Once configured, your AI agent will have access to tools like:
130
133
  - `list_epics` - View epics on the board
131
134
  - `get_iteration_context` - Get current iteration and backlog for planning
132
135
 
136
+ ### TDD Workflow Tools
137
+ These tools enforce Test-Driven Development for AI agents:
138
+
139
+ - `start_story` - Start TDD workflow: creates branch, sets workflow_stage to `tdd_start`
140
+ - `propose_test_plan` - Submit test plan for human review (BLOCKS implementation)
141
+ - `submit_for_review` - Submit implementation for human review (requires approved tests)
142
+
143
+ See the [TDD Workflow Guide](/docs/tdd-workflow) for the complete workflow.
144
+
145
+ > [!NOTE]
146
+ > Many MCP clients namespace tools by server name. If your MCP config uses the
147
+ > server key `"elixium"`, Codex will typically expose these tools as
148
+ > `mcp_elixium_list_stories`, `mcp_elixium_get_iteration_context`, etc.
149
+
150
+ ## Initialize Agent Workflows
151
+
152
+ New projects can scaffold the agent workflow documentation with:
153
+
154
+ ```bash
155
+ npx @elixium.ai/mcp-server init
156
+ ```
157
+
158
+ This creates `.agent/workflows/` with:
159
+ - `implement-story.md` - TDD implementation workflow
160
+ - `manage-board.md` - Board management commands
161
+ - `load-board-context.md` - Session context loading
162
+
163
+ If you already have workflows and want to restore the originals:
164
+ ```bash
165
+ rm -rf .agent/workflows
166
+ npx @elixium.ai/mcp-server init
167
+ ```
168
+
133
169
  ## Development (Source Build)
134
170
  If you're contributing or developing from source:
135
171
 
package/dist/index.js CHANGED
@@ -9,6 +9,7 @@ const API_KEY = process.env.ELIXIUM_API_KEY;
9
9
  const API_URL = process.env.ELIXIUM_API_URL || "https://elixium.ai/api";
10
10
  const BOARD_SLUG = process.env.ELIXIUM_BOARD_SLUG;
11
11
  const LANE_STYLE_ENV = process.env.ELIXIUM_LANE_STYLE;
12
+ const USER_EMAIL = process.env.ELIXIUM_USER_EMAIL; // Optional: Override requester email for stories
12
13
  const CLI_ARGS = process.argv.slice(2);
13
14
  const hasArg = (flag) => CLI_ARGS.includes(flag);
14
15
  const getArgValue = (flag) => {
@@ -276,6 +277,10 @@ const createServer = () => {
276
277
  type: "number",
277
278
  description: "Points (0, 1, 2, 3, 5, 8)",
278
279
  },
280
+ requester: {
281
+ type: "string",
282
+ description: "Email of the person requesting this story. Defaults to ELIXIUM_USER_EMAIL env var or API key owner.",
283
+ },
279
284
  },
280
285
  required: ["title"],
281
286
  },
@@ -350,13 +355,21 @@ const createServer = () => {
350
355
  description: "Roadmap stage",
351
356
  enum: ["in_progress", "next", "soon", "someday", "archived"],
352
357
  },
358
+ hypothesis: { type: "string", description: "We believe that... (outcome hypothesis)" },
359
+ successMetrics: { type: "string", description: "We'll know it works when... (success criteria)" },
360
+ targetDate: { type: "number", description: "Unix timestamp - when to evaluate outcome (not ship date)" },
361
+ outcomeStatus: {
362
+ type: "string",
363
+ description: "Outcome validation status",
364
+ enum: ["exploring", "validating", "achieved", "abandoned"],
365
+ },
353
366
  },
354
367
  required: ["title"],
355
368
  },
356
369
  },
357
370
  {
358
371
  name: "update_epic",
359
- description: "Update an epic (title, description, or stage)",
372
+ description: "Update an epic (title, description, stage, or outcome fields)",
360
373
  inputSchema: {
361
374
  type: "object",
362
375
  properties: {
@@ -368,6 +381,14 @@ const createServer = () => {
368
381
  description: "Roadmap stage",
369
382
  enum: ["in_progress", "next", "soon", "someday", "archived"],
370
383
  },
384
+ hypothesis: { type: "string", description: "We believe that... (outcome hypothesis)" },
385
+ successMetrics: { type: "string", description: "We'll know it works when... (success criteria)" },
386
+ targetDate: { type: "number", description: "Unix timestamp - when to evaluate outcome (not ship date)" },
387
+ outcomeStatus: {
388
+ type: "string",
389
+ description: "Outcome validation status",
390
+ enum: ["exploring", "validating", "achieved", "abandoned"],
391
+ },
371
392
  },
372
393
  required: ["epicId"],
373
394
  },
@@ -429,6 +450,79 @@ const createServer = () => {
429
450
  required: ["storyId"],
430
451
  },
431
452
  },
453
+ // TDD Workflow Tools
454
+ {
455
+ name: "start_story",
456
+ description: "Start TDD workflow for a story. By default creates a feature branch. Set trunkBased=true to work directly on main (recommended for small changes).",
457
+ inputSchema: {
458
+ type: "object",
459
+ properties: {
460
+ storyId: {
461
+ type: "string",
462
+ description: "ID of the story to start",
463
+ },
464
+ branchPrefix: {
465
+ type: "string",
466
+ description: "Branch prefix (feat, fix, chore) - ignored if trunkBased=true",
467
+ enum: ["feat", "fix", "chore"],
468
+ },
469
+ trunkBased: {
470
+ type: "boolean",
471
+ description: "If true, skip branch creation and commit directly to main. Recommended for small, well-tested changes.",
472
+ },
473
+ },
474
+ required: ["storyId"],
475
+ },
476
+ },
477
+ {
478
+ name: "propose_test_plan",
479
+ description: "Submit a test plan for human review. Sets workflow_stage to tests_proposed. Implementation is BLOCKED until human approves.",
480
+ inputSchema: {
481
+ type: "object",
482
+ properties: {
483
+ storyId: {
484
+ type: "string",
485
+ description: "ID of the story",
486
+ },
487
+ testPlan: {
488
+ type: "string",
489
+ description: "Markdown test plan describing test strategy",
490
+ },
491
+ testFilePaths: {
492
+ type: "array",
493
+ items: { type: "string" },
494
+ description: "Paths to created test files",
495
+ },
496
+ },
497
+ required: ["storyId", "testPlan"],
498
+ },
499
+ },
500
+ {
501
+ name: "submit_for_review",
502
+ description: "Submit implementation for human review. Only works if tests are approved. Sets state to finished.",
503
+ inputSchema: {
504
+ type: "object",
505
+ properties: {
506
+ storyId: {
507
+ type: "string",
508
+ description: "ID of the story",
509
+ },
510
+ commitHash: {
511
+ type: "string",
512
+ description: "Latest commit SHA",
513
+ },
514
+ testResults: {
515
+ type: "string",
516
+ description: "Test output summary",
517
+ },
518
+ implementationNotes: {
519
+ type: "string",
520
+ description: "What was implemented",
521
+ },
522
+ },
523
+ required: ["storyId"],
524
+ },
525
+ },
432
526
  ],
433
527
  };
434
528
  });
@@ -448,10 +542,13 @@ const createServer = () => {
448
542
  const args = request.params.arguments;
449
543
  const normalizedLane = await normalizeLane(args.lane);
450
544
  const boardId = await resolveBoardId();
545
+ // Use requester from args, fall back to env var, then let backend use API key owner
546
+ const requester = args.requester || USER_EMAIL;
451
547
  const response = await client.post("/stories", {
452
548
  ...args,
453
549
  lane: normalizedLane,
454
550
  ...(boardId ? { boardId } : {}),
551
+ ...(requester ? { requester } : {}),
455
552
  });
456
553
  return {
457
554
  content: [
@@ -489,11 +586,14 @@ const createServer = () => {
489
586
  const args = request.params.arguments;
490
587
  const normalizedLane = await normalizeLane("Icebox");
491
588
  const boardId = await resolveBoardId();
589
+ // Use requester from env var if set
590
+ const requester = USER_EMAIL;
492
591
  // Enforce Icebox lane
493
592
  const payload = {
494
593
  ...args,
495
594
  lane: normalizedLane, // Map to lane style expected by API
496
595
  ...(boardId ? { boardId } : {}),
596
+ ...(requester ? { requester } : {}),
497
597
  };
498
598
  const response = await client.post("/stories", payload);
499
599
  return {
@@ -621,6 +721,122 @@ Here’s the smallest change that will validate it:
621
721
  content: [{ type: "text", text: formattedBrief.trim() }],
622
722
  };
623
723
  }
724
+ // TDD Workflow Handlers
725
+ case "start_story": {
726
+ const args = request.params.arguments;
727
+ const { storyId, branchPrefix, trunkBased } = args;
728
+ if (!storyId) {
729
+ throw new Error("storyId is required");
730
+ }
731
+ const response = await client.post(`/stories/${storyId}/start`, {
732
+ branchPrefix: branchPrefix || "feat",
733
+ trunkBased: trunkBased || false,
734
+ });
735
+ const result = response.data;
736
+ const isTrunk = trunkBased || result.branch === "main";
737
+ const formattedResult = isTrunk ? `
738
+ # Story Started (Trunk-Based): ${storyId}
739
+
740
+ **Mode:** 🚀 Direct to main (trunk-based development)
741
+ **Workflow Stage:** ${result.workflow_stage}
742
+
743
+ ## Acceptance Criteria
744
+ ${result.acceptance_criteria || "No specific AC provided."}
745
+
746
+ ## Trunk-Based Workflow
747
+ 1. ✅ Write tests first
748
+ 2. ✅ Call \`propose_test_plan\` and wait for approval
749
+ 3. ✅ Implement (make tests pass)
750
+ 4. ✅ Run \`npm run build\` to verify
751
+ 5. ✅ Commit directly to main
752
+ 6. 🚀 Auto-deploy on green CI
753
+
754
+ > ⚠️ **TDD Workflow:** Write tests first, then call \`propose_test_plan\` before implementing.
755
+ ` : `
756
+ # Story Started: ${storyId}
757
+
758
+ **Branch:** \`${result.branch}\`
759
+ **Workflow Stage:** ${result.workflow_stage}
760
+
761
+ ## Acceptance Criteria
762
+ ${result.acceptance_criteria || "No specific AC provided."}
763
+
764
+ ## Next Steps
765
+ ${result.workflow_reminder}
766
+
767
+ > ⚠️ **TDD Workflow:** Write tests first, then call \`propose_test_plan\` before implementing.
768
+ `;
769
+ return {
770
+ content: [{ type: "text", text: formattedResult.trim() }],
771
+ };
772
+ }
773
+ case "propose_test_plan": {
774
+ const args = request.params.arguments;
775
+ const { storyId, testPlan, testFilePaths } = args;
776
+ if (!storyId) {
777
+ throw new Error("storyId is required");
778
+ }
779
+ if (!testPlan) {
780
+ throw new Error("testPlan is required");
781
+ }
782
+ const response = await client.post(`/stories/${storyId}/propose-tests`, {
783
+ testPlan,
784
+ testFilePaths,
785
+ });
786
+ const result = response.data;
787
+ const formattedResult = `
788
+ # Test Plan Proposed
789
+
790
+ **Story ID:** ${storyId}
791
+ **Workflow Stage:** ${result.workflow_stage}
792
+
793
+ ## Test Files
794
+ ${(result.test_file_paths || []).map((p) => `- \`${p}\``).join("\n") || "No test files specified"}
795
+
796
+ ## Status
797
+ ${result.message}
798
+
799
+ > 🛑 **BLOCKED:** Implementation cannot proceed until a human approves this test plan.
800
+ `;
801
+ return {
802
+ content: [{ type: "text", text: formattedResult.trim() }],
803
+ };
804
+ }
805
+ case "submit_for_review": {
806
+ const args = request.params.arguments;
807
+ const { storyId, commitHash, testResults, implementationNotes } = args;
808
+ if (!storyId) {
809
+ throw new Error("storyId is required");
810
+ }
811
+ const response = await client.post(`/stories/${storyId}/submit-review`, {
812
+ commitHash,
813
+ testResults,
814
+ implementationNotes,
815
+ });
816
+ const result = response.data;
817
+ const formattedResult = `
818
+ # Implementation Submitted for Review
819
+
820
+ **Story ID:** ${storyId}
821
+ **Status:** ${result.status}
822
+ **Workflow Stage:** ${result.workflow_stage}
823
+ **State:** ${result.state}
824
+
825
+ ## Branch
826
+ \`${result.branch || "No branch recorded"}\`
827
+
828
+ ## Commits
829
+ ${(result.commit_hashes || []).map((h) => `- \`${h}\``).join("\n") || "No commits recorded"}
830
+
831
+ ## Next Step
832
+ ${result.next_step}
833
+
834
+ > ✅ **Ready for Review:** Human should review diff and move story to Done lane.
835
+ `;
836
+ return {
837
+ content: [{ type: "text", text: formattedResult.trim() }],
838
+ };
839
+ }
624
840
  default:
625
841
  throw new Error("Unknown tool");
626
842
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@elixium.ai/mcp-server",
3
- "version": "0.1.6",
3
+ "version": "0.1.8",
4
4
  "type": "module",
5
5
  "description": "MCP Server for Elixium.ai",
6
6
  "publishConfig": {
@@ -4,16 +4,89 @@ description: How to implement an Elixium story using the agent and MCP
4
4
 
5
5
  Follow this workflow when a developer selects a story for implementation.
6
6
 
7
+ > [!IMPORTANT]
8
+ > This workflow enforces **Test-Driven Development**. You cannot skip tests.
9
+
10
+ ## Workflow Modes
11
+
12
+ | Mode | When to Use | Branch Strategy |
13
+ |------|-------------|-----------------|
14
+ | **Trunk-Based** (recommended) | Small, well-scoped stories (<1 day) | Direct to `main` |
15
+ | **Branch-Based** | Large features, breaking changes | Feature branch → PR → merge |
16
+
17
+ ### 0. Check the North Star
18
+ - **Before any implementation**, read `docs/NORTHSTAR.md` to understand current priorities and principles.
19
+ - Verify the story aligns with the decision framework.
20
+ - If unsure, ask: *"Does this work offline? Is it additive, not modifying?"*
21
+
7
22
  ### 1. Identify & Prepare the Story
8
23
  - Ask the developer which story they want to work on, or list the stories in the **Current** lane using `mcp_elixium_list_stories`.
9
24
  - Once a story is selected, run the `mcp_elixium_prepare_implementation` tool.
25
+ - Collaborate with developer to refine description and acceptance criteria if needed.
26
+
27
+ ### 2. Start TDD Workflow (MANDATORY)
28
+ - Call `mcp_elixium_start_story` with the storyId.
29
+ - **For trunk-based (default for small changes):** Add `trunkBased: true`
30
+ - **For branch-based (large features):** Omit trunkBased or set to false
31
+ - This sets `workflow_stage: tdd_start`.
32
+
33
+ ```
34
+ // Trunk-based (recommended for most stories)
35
+ mcp_elixium_start_story({ storyId: "abc123", trunkBased: true })
36
+
37
+ // Branch-based (for larger features)
38
+ mcp_elixium_start_story({ storyId: "abc123", branchPrefix: "feat" })
39
+ ```
40
+
41
+ ### 3. Write Tests First (MANDATORY)
42
+ - Create test files that cover the acceptance criteria.
43
+ - Call `mcp_elixium_propose_test_plan` with:
44
+ - `storyId`: The story ID
45
+ - `testPlan`: Markdown describing your test strategy
46
+ - `testFilePaths`: Array of test file paths you created
47
+
48
+ > [!WARNING]
49
+ > **BLOCKED**: You cannot proceed to implementation until the human approves the test plan.
50
+ > The API will reject `submit_for_review` if tests are not approved.
51
+
52
+ ### 4. Wait for Human Approval
53
+ - The developer will see the "Test Plan" tab in the Elixium UI.
54
+ - They will review your tests and click "Approve Test Plan".
55
+ - Once approved, `workflow_stage` changes to `tests_approved`.
56
+
57
+ ### 5. Implement (Make Tests Pass)
58
+ - Write the minimal code to make tests pass.
59
+ - Run tests frequently: `npm test` or `npx playwright test`.
60
+ - Keep changes small and focused.
61
+
62
+ ### 6. Build Verification (MANDATORY before push)
63
+ - **Run `npm run build`** before EVERY commit/push.
64
+ - This catches:
65
+ - TypeScript errors
66
+ - ESLint issues
67
+ - SSR prerendering failures (e.g., missing Suspense boundaries)
68
+ - Next.js-specific requirements
69
+ - **DO NOT PUSH if the build fails.**
70
+ - `npx tsc --noEmit` is NOT sufficient - it only checks types, not runtime/SSR issues.
71
+
72
+ ### 7. Submit for Review
73
+ - Call `mcp_elixium_submit_for_review` with:
74
+ - `storyId`: The story ID
75
+ - `commitHash`: The commit SHA (optional but recommended)
76
+ - `implementationNotes`: Summary of what was implemented
77
+ - This sets `state: finished` and `workflow_stage: review`.
78
+
79
+ ### 8. Merge & Deploy
80
+ - **Trunk-based:** Push to main → CI runs → auto-deploys to prod on green ✅
81
+ - **Branch-based:** Create PR → review → merge → auto-deploys to prod
10
82
 
11
- ### 2. Review the Brief
12
- - The tool will output an **Implementation Brief** containing:
13
- - **Acceptance Criteria**
14
- - **Assumptions / Learning Goals**
15
- - **Guardrail Warnings** (e.g., if the story is in the wrong lane)
83
+ ### 9. Final Human Review
84
+ - The developer reviews the deployment in production.
85
+ - **Only the developer** can move the story to Done lane.
86
+ - **Only the developer** can set state to `accepted`.
16
87
 
17
- ### 3. Propose & Confirm
18
- - Review the brief and add a **Proposal**: "Here’s the smallest change that will validate it: [Describe minimal slice]"
19
- - Only after the developer confirms the plan should the agent transition to `EXECUTION` mode.
88
+ ### 10. Record Learning
89
+ - Before the developer moves to Done, use `mcp_elixium_record_learning` to capture:
90
+ - What was validated?
91
+ - What new risks appeared?
92
+ - What should be preserved for next time?
@@ -9,7 +9,7 @@ Use this workflow at the beginning of a session or when the user asks about boar
9
9
 
10
10
  ### 1. Load context
11
11
  - Call `mcp_elixium_get_iteration_context` immediately.
12
- - Cache the `current` and `backlog` stories for the rest of the session.
12
+ - Cache the returned `currentIteration` and `backlog` lists for the rest of the session.
13
13
 
14
14
  ### 2. Keep context fresh
15
15
  - Re-run `mcp_elixium_get_iteration_context` if the user asks for the “latest” state
@@ -8,6 +8,37 @@ Use this workflow for any project management requests (creating stories, checkin
8
8
  > **ALWAYS** use the `mcp_elixium_*` tools. **NEVER** try to write scripts to interact with the API directly.
9
9
  > The MCP server is your authenticated, context-aware interface to the board.
10
10
 
11
+ ---
12
+
13
+ ## Available Tools
14
+
15
+ ### Board & Story Management
16
+ | Tool | Purpose |
17
+ |------|---------|
18
+ | `mcp_elixium_list_stories` | View all stories on the board |
19
+ | `mcp_elixium_list_epics` | View high-level initiatives |
20
+ | `mcp_elixium_create_story` | Create a new story |
21
+ | `mcp_elixium_update_story` | Update story fields or move lanes |
22
+ | `mcp_elixium_create_epic` | Create a large initiative |
23
+ | `mcp_elixium_update_epic` | Update epic details or stage |
24
+ | `mcp_elixium_create_hypothesis` | Create assumption for validation |
25
+ | `mcp_elixium_get_iteration_context` | Get Current + Backlog for planning |
26
+ | `mcp_elixium_prepare_implementation` | Get full context for a story |
27
+ | `mcp_elixium_record_learning` | Record outcome after completion |
28
+
29
+ ### TDD Workflow Tools (for implementation)
30
+ | Tool | Purpose |
31
+ |------|---------|
32
+ | `mcp_elixium_start_story` | Start TDD workflow, create branch |
33
+ | `mcp_elixium_propose_test_plan` | Submit tests for human approval |
34
+ | `mcp_elixium_submit_for_review` | Submit implementation for review |
35
+
36
+ > See `.agent/workflows/implement-story.md` for the full TDD workflow.
37
+
38
+ ---
39
+
40
+ ## Common Operations
41
+
11
42
  ### 1. View the Board
12
43
  - Use `mcp_elixium_list_stories` to see the current state of the board.
13
44
  - Use `mcp_elixium_list_epics` to see high-level initiatives.