@context-forge/mcp 0.1.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/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2025-2026 Manta Templates
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
package/README.md ADDED
@@ -0,0 +1,102 @@
1
+ # @context-forge/mcp
2
+
3
+ An MCP server that generates structured context prompts for AI coding sessions. Configure your project once, then generate fresh, consistent context whenever you start a new session with Claude Code, Cursor, or any MCP-compatible tool.
4
+
5
+ ## What is this?
6
+
7
+ Every productive AI coding session starts with context: what project you're working on, what slice or task is active, what conventions to follow, what happened in the last session. Context Forge assembles that context automatically from your project configuration and prompt templates.
8
+
9
+ This MCP server exposes Context Forge's context engine as a set of tools that your AI assistant can call directly. Instead of manually copying and pasting context blocks, the assistant generates them on demand — staying current as your work progresses.
10
+
11
+ ## Why?
12
+
13
+ Building context by hand is tedious. Every session, you're pulling together the same pieces: project state, current task, coding conventions, template sections. It takes several minutes, it's error-prone, and it breaks your flow.
14
+
15
+ Context Forge eliminates that overhead. You configure your project once — templates, statements, project structure — and then generate a complete, structured context prompt with a single tool call. When you switch slices, change tasks, or reach a milestone, your assistant updates the project state and the next context generation reflects it automatically.
16
+
17
+ ## Quick Start
18
+
19
+ ### Install
20
+
21
+ ```bash
22
+ # Run directly (no install needed)
23
+ npx @context-forge/mcp
24
+
25
+ # Or install globally
26
+ npm install -g @context-forge/mcp
27
+ ```
28
+
29
+ ### Configure for Claude Code
30
+
31
+ Add the server using the Claude Code CLI:
32
+
33
+ ```bash
34
+ claude mcp add --transport stdio context-forge -- npx @context-forge/mcp
35
+ ```
36
+
37
+ Or add it manually to your project's `.mcp.json`:
38
+
39
+ ```json
40
+ {
41
+ "mcpServers": {
42
+ "context-forge": {
43
+ "type": "stdio",
44
+ "command": "npx",
45
+ "args": ["@context-forge/mcp"]
46
+ }
47
+ }
48
+ }
49
+ ```
50
+
51
+ ### Configure for Cursor
52
+
53
+ Add the following to your Cursor MCP settings (`.cursor/mcp.json` in your project root):
54
+
55
+ ```json
56
+ {
57
+ "mcpServers": {
58
+ "context-forge": {
59
+ "command": "npx",
60
+ "args": ["@context-forge/mcp"]
61
+ }
62
+ }
63
+ }
64
+ ```
65
+
66
+ ## Available Tools
67
+
68
+ | Tool | Description |
69
+ |------|-------------|
70
+ | `project_list` | List all configured projects with summary fields |
71
+ | `project_get` | Get full project details by ID |
72
+ | `project_update` | Update project configuration (slice, instruction, phase, etc.) |
73
+ | `context_build` | Generate a complete context prompt from project configuration |
74
+ | `template_preview` | Preview context output without side effects |
75
+ | `prompt_list` | List available prompt templates for a project |
76
+ | `prompt_get` | Get the full content of a specific prompt template |
77
+ | `context_summarize` | Update project session state (recent events, notes) |
78
+
79
+ For full parameter details, see the [Tool Reference](../../docs/TOOLS.md).
80
+
81
+ ## Prerequisites
82
+
83
+ - **Node.js 18+**
84
+ - **ai-project-guide templates** set up in your project
85
+
86
+ Context Forge uses prompt templates and project structure conventions from [ai-project-guide](https://github.com/ecorkran/ai-project-guide). To bootstrap the templates in your project:
87
+
88
+ ```bash
89
+ curl -fsSL https://raw.githubusercontent.com/ecorkran/ai-project-guide/main/scripts/bootstrap.sh | bash
90
+ ```
91
+
92
+ See the [ai-project-guide repository](https://github.com/ecorkran/ai-project-guide) for details on the methodology and template system.
93
+
94
+ ## Related
95
+
96
+ - [Context Forge](../../README.md) — monorepo root with desktop app and full project documentation
97
+ - [@context-forge/core](../core/README.md) — the context generation engine that powers this server
98
+ - [ai-project-guide](https://github.com/ecorkran/ai-project-guide) — the template system and project methodology
99
+
100
+ ## License
101
+
102
+ MIT
@@ -0,0 +1,3 @@
1
+ #!/usr/bin/env node
2
+ export {};
3
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":""}
package/dist/index.js ADDED
@@ -0,0 +1,31 @@
1
+ #!/usr/bin/env node
2
+ // MCP SDK: @modelcontextprotocol/sdk v1.26.0 (v1 monolithic package)
3
+ // Zod: v4.1.5 — imported as `z` from 'zod'
4
+ import { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';
5
+ import { StdioServerTransport } from '@modelcontextprotocol/sdk/server/stdio.js';
6
+ import { registerProjectTools } from './tools/projectTools.js';
7
+ import { registerContextTools } from './tools/contextTools.js';
8
+ import { registerStateTools } from './tools/stateTools.js';
9
+ const SERVER_NAME = 'context-forge-mcp';
10
+ const SERVER_VERSION = '0.1.0';
11
+ function log(message) {
12
+ console.error(`[${SERVER_NAME}] ${message}`);
13
+ }
14
+ async function main() {
15
+ const server = new McpServer({
16
+ name: SERVER_NAME,
17
+ version: SERVER_VERSION,
18
+ });
19
+ registerProjectTools(server);
20
+ registerContextTools(server);
21
+ registerStateTools(server);
22
+ const transport = new StdioServerTransport();
23
+ await server.connect(transport);
24
+ log('Server started');
25
+ }
26
+ main().catch((error) => {
27
+ const message = error instanceof Error ? error.message : String(error);
28
+ console.error(`[${SERVER_NAME}] Fatal error: ${message}`);
29
+ process.exit(1);
30
+ });
31
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":";AACA,qEAAqE;AACrE,2CAA2C;AAE3C,OAAO,EAAE,SAAS,EAAE,MAAM,yCAAyC,CAAC;AACpE,OAAO,EAAE,oBAAoB,EAAE,MAAM,2CAA2C,CAAC;AACjF,OAAO,EAAE,oBAAoB,EAAE,MAAM,yBAAyB,CAAC;AAC/D,OAAO,EAAE,oBAAoB,EAAE,MAAM,yBAAyB,CAAC;AAC/D,OAAO,EAAE,kBAAkB,EAAE,MAAM,uBAAuB,CAAC;AAE3D,MAAM,WAAW,GAAG,mBAAmB,CAAC;AACxC,MAAM,cAAc,GAAG,OAAO,CAAC;AAE/B,SAAS,GAAG,CAAC,OAAe;IAC1B,OAAO,CAAC,KAAK,CAAC,IAAI,WAAW,KAAK,OAAO,EAAE,CAAC,CAAC;AAC/C,CAAC;AAED,KAAK,UAAU,IAAI;IACjB,MAAM,MAAM,GAAG,IAAI,SAAS,CAAC;QAC3B,IAAI,EAAE,WAAW;QACjB,OAAO,EAAE,cAAc;KACxB,CAAC,CAAC;IAEH,oBAAoB,CAAC,MAAM,CAAC,CAAC;IAC7B,oBAAoB,CAAC,MAAM,CAAC,CAAC;IAC7B,kBAAkB,CAAC,MAAM,CAAC,CAAC;IAE3B,MAAM,SAAS,GAAG,IAAI,oBAAoB,EAAE,CAAC;IAC7C,MAAM,MAAM,CAAC,OAAO,CAAC,SAAS,CAAC,CAAC;IAEhC,GAAG,CAAC,gBAAgB,CAAC,CAAC;AACxB,CAAC;AAED,IAAI,EAAE,CAAC,KAAK,CAAC,CAAC,KAAc,EAAE,EAAE;IAC9B,MAAM,OAAO,GAAG,KAAK,YAAY,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC;IACvE,OAAO,CAAC,KAAK,CAAC,IAAI,WAAW,kBAAkB,OAAO,EAAE,CAAC,CAAC;IAC1D,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;AAClB,CAAC,CAAC,CAAC"}
@@ -0,0 +1,28 @@
1
+ import { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';
2
+ import type { ProjectData } from '@context-forge/core';
3
+ export declare function errorResult(message: string): {
4
+ content: {
5
+ type: 'text';
6
+ text: string;
7
+ }[];
8
+ isError: true;
9
+ };
10
+ export declare function textResult(text: string): {
11
+ content: {
12
+ type: 'text';
13
+ text: string;
14
+ }[];
15
+ };
16
+ export declare function jsonResult(data: unknown): {
17
+ content: {
18
+ type: 'text';
19
+ text: string;
20
+ }[];
21
+ };
22
+ /**
23
+ * Shared context generation helper used by context_build and template_preview.
24
+ * Loads a project, applies optional overrides, generates context via core pipeline.
25
+ */
26
+ export declare function generateContext(projectId: string, overrides?: Partial<ProjectData>, additionalInstructions?: string): Promise<string>;
27
+ export declare function registerContextTools(server: McpServer): void;
28
+ //# sourceMappingURL=contextTools.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"contextTools.d.ts","sourceRoot":"","sources":["../../src/tools/contextTools.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,SAAS,EAAE,MAAM,yCAAyC,CAAC;AAIpE,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,qBAAqB,CAAC;AAIvD,wBAAgB,WAAW,CAAC,OAAO,EAAE,MAAM,GAAG;IAAE,OAAO,EAAE;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,IAAI,EAAE,MAAM,CAAA;KAAE,EAAE,CAAC;IAAC,OAAO,EAAE,IAAI,CAAA;CAAE,CAEzG;AAED,wBAAgB,UAAU,CAAC,IAAI,EAAE,MAAM,GAAG;IAAE,OAAO,EAAE;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,IAAI,EAAE,MAAM,CAAA;KAAE,EAAE,CAAA;CAAE,CAEtF;AAED,wBAAgB,UAAU,CAAC,IAAI,EAAE,OAAO,GAAG;IAAE,OAAO,EAAE;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,IAAI,EAAE,MAAM,CAAA;KAAE,EAAE,CAAA;CAAE,CAEvF;AAED;;;GAGG;AACH,wBAAsB,eAAe,CACnC,SAAS,EAAE,MAAM,EACjB,SAAS,CAAC,EAAE,OAAO,CAAC,WAAW,CAAC,EAChC,sBAAsB,CAAC,EAAE,MAAM,GAC9B,OAAO,CAAC,MAAM,CAAC,CAkCjB;AAeD,wBAAgB,oBAAoB,CAAC,MAAM,EAAE,SAAS,GAAG,IAAI,CAwK5D"}
@@ -0,0 +1,172 @@
1
+ import * as path from 'node:path';
2
+ import { z } from 'zod';
3
+ import { FileProjectStore, createContextPipeline, SystemPromptParser } from '@context-forge/core/node';
4
+ import { PROMPT_FILE_RELATIVE_PATH } from '@context-forge/core';
5
+ // --- Shared helpers ---
6
+ export function errorResult(message) {
7
+ return { content: [{ type: 'text', text: message }], isError: true };
8
+ }
9
+ export function textResult(text) {
10
+ return { content: [{ type: 'text', text }] };
11
+ }
12
+ export function jsonResult(data) {
13
+ return { content: [{ type: 'text', text: JSON.stringify(data, null, 2) }] };
14
+ }
15
+ /**
16
+ * Shared context generation helper used by context_build and template_preview.
17
+ * Loads a project, applies optional overrides, generates context via core pipeline.
18
+ */
19
+ export async function generateContext(projectId, overrides, additionalInstructions) {
20
+ const store = new FileProjectStore();
21
+ const project = await store.getById(projectId);
22
+ if (!project) {
23
+ throw new Error(`Project not found: '${projectId}'. Use the project_list tool to see available projects and their IDs.`);
24
+ }
25
+ if (!project.projectPath) {
26
+ throw new Error(`Project '${project.name}' has no configured project path. Set a project path before generating context.`);
27
+ }
28
+ // Create working copy with overrides applied
29
+ const workingCopy = { ...project };
30
+ if (overrides) {
31
+ for (const [key, value] of Object.entries(overrides)) {
32
+ if (value !== undefined) {
33
+ workingCopy[key] = value;
34
+ }
35
+ }
36
+ }
37
+ const { integrator } = createContextPipeline(workingCopy.projectPath);
38
+ let contextString = await integrator.generateContextFromProject(workingCopy);
39
+ if (additionalInstructions) {
40
+ contextString = `${contextString}\n\n${additionalInstructions}`;
41
+ }
42
+ return contextString;
43
+ }
44
+ /** Zod schema for optional project parameter overrides */
45
+ const contextOverridesSchema = {
46
+ projectId: z.string().describe('Project ID. Use project_list to find IDs.'),
47
+ slice: z.string().optional().describe('Override the current slice name'),
48
+ taskFile: z.string().optional().describe('Override the task file name'),
49
+ instruction: z.string().optional().describe('Override the instruction type (e.g., implementation, design, review)'),
50
+ developmentPhase: z.string().optional().describe('Override the current development phase'),
51
+ workType: z.enum(['start', 'continue']).optional().describe('Override whether starting or continuing work'),
52
+ additionalInstructions: z.string().optional().describe('Additional instructions to append to the generated context'),
53
+ };
54
+ // --- Tool registration ---
55
+ export function registerContextTools(server) {
56
+ // --- context_build ---
57
+ server.registerTool('context_build', {
58
+ title: 'Build Context',
59
+ description: 'Build a complete context prompt for a Context Forge project. This is the primary tool for generating structured context blocks. Optionally override project parameters (slice, instruction, etc.) without modifying the stored project. Returns the assembled context ready for use.',
60
+ inputSchema: contextOverridesSchema,
61
+ annotations: { readOnlyHint: false, idempotentHint: true, openWorldHint: false },
62
+ }, async ({ projectId, additionalInstructions, ...overrideFields }) => {
63
+ try {
64
+ // Collect defined overrides
65
+ const overrides = {};
66
+ for (const [key, value] of Object.entries(overrideFields)) {
67
+ if (value !== undefined) {
68
+ overrides[key] = value;
69
+ }
70
+ }
71
+ const contextString = await generateContext(projectId, Object.keys(overrides).length > 0 ? overrides : undefined, additionalInstructions);
72
+ return textResult(contextString);
73
+ }
74
+ catch (error) {
75
+ const message = error instanceof Error ? error.message : String(error);
76
+ return errorResult(message);
77
+ }
78
+ });
79
+ // --- template_preview ---
80
+ server.registerTool('template_preview', {
81
+ title: 'Preview Context',
82
+ description: 'Preview a context prompt with specified parameters without modifying the stored project or triggering any side effects. Use this to explore what context would be generated with different configurations before committing to a context_build.',
83
+ inputSchema: contextOverridesSchema,
84
+ annotations: { readOnlyHint: true, idempotentHint: true, openWorldHint: false },
85
+ }, async ({ projectId, additionalInstructions, ...overrideFields }) => {
86
+ try {
87
+ const overrides = {};
88
+ for (const [key, value] of Object.entries(overrideFields)) {
89
+ if (value !== undefined) {
90
+ overrides[key] = value;
91
+ }
92
+ }
93
+ const contextString = await generateContext(projectId, Object.keys(overrides).length > 0 ? overrides : undefined, additionalInstructions);
94
+ return textResult(contextString);
95
+ }
96
+ catch (error) {
97
+ const message = error instanceof Error ? error.message : String(error);
98
+ return errorResult(message);
99
+ }
100
+ });
101
+ // --- prompt_list ---
102
+ server.registerTool('prompt_list', {
103
+ title: 'List Prompts',
104
+ description: 'List available prompt templates for a Context Forge project. Returns template names and metadata. Use prompt_get to retrieve the full content of a specific template.',
105
+ inputSchema: {
106
+ projectId: z.string().describe('Project ID. Use project_list to find IDs.'),
107
+ },
108
+ annotations: { readOnlyHint: true, openWorldHint: false },
109
+ }, async ({ projectId }) => {
110
+ try {
111
+ const store = new FileProjectStore();
112
+ const project = await store.getById(projectId);
113
+ if (!project) {
114
+ return errorResult(`Project not found: '${projectId}'. Use the project_list tool to see available projects and their IDs.`);
115
+ }
116
+ if (!project.projectPath) {
117
+ return errorResult(`Project '${project.name}' has no configured project path. Set a project path before listing prompts.`);
118
+ }
119
+ const promptFilePath = path.join(project.projectPath, PROMPT_FILE_RELATIVE_PATH);
120
+ const parser = new SystemPromptParser(promptFilePath);
121
+ const prompts = await parser.getAllPrompts();
122
+ const templates = prompts.map((p) => ({
123
+ name: p.name,
124
+ key: p.key,
125
+ parameterCount: p.parameters.length,
126
+ }));
127
+ return jsonResult({ templates, count: templates.length, promptFile: promptFilePath });
128
+ }
129
+ catch (error) {
130
+ const message = error instanceof Error ? error.message : String(error);
131
+ return errorResult(message);
132
+ }
133
+ });
134
+ // --- prompt_get ---
135
+ server.registerTool('prompt_get', {
136
+ title: 'Get Prompt',
137
+ description: 'Get the full content of a specific prompt template. Returns the raw template text. Useful for inspecting what a template contains before building context with it.',
138
+ inputSchema: {
139
+ projectId: z.string().describe('Project ID. Use project_list to find IDs.'),
140
+ templateName: z.string().describe('Template name or key to match. Use prompt_list to see available templates.'),
141
+ },
142
+ annotations: { readOnlyHint: true, openWorldHint: false },
143
+ }, async ({ projectId, templateName }) => {
144
+ try {
145
+ const store = new FileProjectStore();
146
+ const project = await store.getById(projectId);
147
+ if (!project) {
148
+ return errorResult(`Project not found: '${projectId}'. Use the project_list tool to see available projects and their IDs.`);
149
+ }
150
+ if (!project.projectPath) {
151
+ return errorResult(`Project '${project.name}' has no configured project path. Set a project path before retrieving prompts.`);
152
+ }
153
+ const promptFilePath = path.join(project.projectPath, PROMPT_FILE_RELATIVE_PATH);
154
+ const parser = new SystemPromptParser(promptFilePath);
155
+ const prompts = await parser.getAllPrompts();
156
+ // Match by name (case-insensitive) or key (exact)
157
+ const templateNameLower = templateName.toLowerCase();
158
+ const match = prompts.find((p) => p.name.toLowerCase() === templateNameLower || p.key === templateName);
159
+ if (!match) {
160
+ return errorResult(`Template not found: '${templateName}'. Use the prompt_list tool to see available templates for this project.`);
161
+ }
162
+ // Return metadata header followed by template content
163
+ const header = `# ${match.name}\nKey: ${match.key}\nParameters: ${match.parameters.join(', ') || 'none'}\n\n---\n\n`;
164
+ return textResult(header + match.content);
165
+ }
166
+ catch (error) {
167
+ const message = error instanceof Error ? error.message : String(error);
168
+ return errorResult(message);
169
+ }
170
+ });
171
+ }
172
+ //# sourceMappingURL=contextTools.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"contextTools.js","sourceRoot":"","sources":["../../src/tools/contextTools.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,3 @@
1
+ import { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';
2
+ export declare function registerProjectTools(server: McpServer): void;
3
+ //# sourceMappingURL=projectTools.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"projectTools.d.ts","sourceRoot":"","sources":["../../src/tools/projectTools.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,MAAM,yCAAyC,CAAC;AAsCpE,wBAAgB,oBAAoB,CAAC,MAAM,EAAE,SAAS,GAAG,IAAI,CA0H5D"}
@@ -0,0 +1,119 @@
1
+ import { z } from 'zod';
2
+ import { FileProjectStore } from '@context-forge/core/node';
3
+ function toSummary(project) {
4
+ return {
5
+ id: project.id,
6
+ name: project.name,
7
+ slice: project.slice,
8
+ template: project.template,
9
+ instruction: project.instruction,
10
+ isMonorepo: project.isMonorepo,
11
+ projectPath: project.projectPath,
12
+ updatedAt: project.updatedAt,
13
+ };
14
+ }
15
+ function errorResult(message) {
16
+ return { content: [{ type: 'text', text: message }], isError: true };
17
+ }
18
+ function jsonResult(data) {
19
+ return { content: [{ type: 'text', text: JSON.stringify(data, null, 2) }] };
20
+ }
21
+ export function registerProjectTools(server) {
22
+ // --- project_list ---
23
+ server.registerTool('project_list', {
24
+ title: 'List Projects',
25
+ description: 'List all configured Context Forge projects. Returns project IDs, names, current slices, and other summary fields. Use this to discover available projects before calling project_get or project_update.',
26
+ inputSchema: {},
27
+ annotations: { readOnlyHint: true, openWorldHint: false },
28
+ }, async () => {
29
+ try {
30
+ const store = new FileProjectStore();
31
+ const allProjects = await store.getAll();
32
+ const projects = allProjects.map(toSummary);
33
+ return jsonResult({ projects, count: projects.length });
34
+ }
35
+ catch (error) {
36
+ const message = error instanceof Error ? error.message : String(error);
37
+ return errorResult(`Error: ${message}`);
38
+ }
39
+ });
40
+ // --- project_get ---
41
+ server.registerTool('project_get', {
42
+ title: 'Get Project',
43
+ description: 'Get full details for a specific Context Forge project by ID. Returns all project fields including configuration, custom data, and timestamps. Use project_list first to find project IDs.',
44
+ inputSchema: {
45
+ id: z.string().describe('Project ID (e.g., project_1739...). Use project_list to find IDs.'),
46
+ },
47
+ annotations: { readOnlyHint: true, openWorldHint: false },
48
+ }, async ({ id }) => {
49
+ try {
50
+ const store = new FileProjectStore();
51
+ const project = await store.getById(id);
52
+ if (!project) {
53
+ return errorResult(`Project not found: '${id}'. Use the project_list tool to see available projects and their IDs.`);
54
+ }
55
+ return jsonResult(project);
56
+ }
57
+ catch (error) {
58
+ const message = error instanceof Error ? error.message : String(error);
59
+ return errorResult(`Error: ${message}`);
60
+ }
61
+ });
62
+ // --- project_update ---
63
+ server.registerTool('project_update', {
64
+ title: 'Update Project',
65
+ description: 'Update configuration fields on an existing Context Forge project. Provide the project ID and any fields to change (e.g., slice, instruction, developmentPhase). Returns the full updated project. Does not delete or replace — only modifies specified fields.',
66
+ inputSchema: {
67
+ id: z.string().describe('Project ID to update'),
68
+ name: z.string().optional().describe('Project display name'),
69
+ template: z.string().optional().describe('Template name'),
70
+ slice: z.string().optional().describe('Current slice name'),
71
+ taskFile: z.string().optional().describe('Task file name'),
72
+ instruction: z.string().optional().describe('Instruction type (e.g., implementation, design, review)'),
73
+ developmentPhase: z.string().optional().describe('Current development phase'),
74
+ workType: z.enum(['start', 'continue']).optional().describe('Whether starting or continuing work'),
75
+ projectDate: z.string().optional().describe('Project date string'),
76
+ isMonorepo: z.boolean().optional().describe('Whether project uses monorepo mode'),
77
+ isMonorepoEnabled: z.boolean().optional().describe('Whether monorepo UI is enabled'),
78
+ projectPath: z.string().optional().describe('Absolute path to project root'),
79
+ customData: z
80
+ .object({
81
+ recentEvents: z.string().optional(),
82
+ additionalNotes: z.string().optional(),
83
+ monorepoNote: z.string().optional(),
84
+ availableTools: z.string().optional(),
85
+ })
86
+ .optional()
87
+ .describe('Custom data fields for context generation'),
88
+ },
89
+ annotations: { destructiveHint: false, idempotentHint: true, openWorldHint: false },
90
+ }, async ({ id, ...fields }) => {
91
+ try {
92
+ // Collect defined update fields (exclude undefined values)
93
+ const updates = {};
94
+ for (const [key, value] of Object.entries(fields)) {
95
+ if (value !== undefined) {
96
+ updates[key] = value;
97
+ }
98
+ }
99
+ if (Object.keys(updates).length === 0) {
100
+ return errorResult('No update fields provided. Specify at least one field to update (e.g., slice, instruction, name).');
101
+ }
102
+ const store = new FileProjectStore();
103
+ // Check project exists
104
+ const existing = await store.getById(id);
105
+ if (!existing) {
106
+ return errorResult(`Project not found: '${id}'. Use the project_list tool to see available projects and their IDs.`);
107
+ }
108
+ await store.update(id, updates);
109
+ // Read back updated project
110
+ const updated = await store.getById(id);
111
+ return jsonResult(updated);
112
+ }
113
+ catch (error) {
114
+ const message = error instanceof Error ? error.message : String(error);
115
+ return errorResult(`Error: ${message}`);
116
+ }
117
+ });
118
+ }
119
+ //# sourceMappingURL=projectTools.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"projectTools.js","sourceRoot":"","sources":["../../src/tools/projectTools.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,3 @@
1
+ import { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';
2
+ export declare function registerStateTools(server: McpServer): void;
3
+ //# sourceMappingURL=stateTools.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"stateTools.d.ts","sourceRoot":"","sources":["../../src/tools/stateTools.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,MAAM,yCAAyC,CAAC;AAKpE,wBAAgB,kBAAkB,CAAC,MAAM,EAAE,SAAS,GAAG,IAAI,CAiE1D"}
@@ -0,0 +1,53 @@
1
+ import { z } from 'zod';
2
+ import { FileProjectStore } from '@context-forge/core/node';
3
+ import { errorResult, jsonResult } from './contextTools.js';
4
+ export function registerStateTools(server) {
5
+ // --- context_summarize ---
6
+ server.registerTool('context_summarize', {
7
+ title: 'Summarize Context',
8
+ description: "Update a project's session state summary. Persists the provided summary text as the project's recent events, " +
9
+ 'which will be included in subsequent context_build output. Use this after significant work milestones, context ' +
10
+ "switches, or to record session progress for continuity. Analogous to Claude Code's /compact but for project-level state.",
11
+ inputSchema: {
12
+ projectId: z.string().describe('Project ID to update. Use project_list to find IDs.'),
13
+ summary: z
14
+ .string()
15
+ .describe('Summary of recent events, session progress, or current project state. ' +
16
+ 'This replaces the current recentEvents field and will appear in subsequent context_build output.'),
17
+ additionalNotes: z
18
+ .string()
19
+ .optional()
20
+ .describe('Optional additional notes to persist alongside the summary. ' +
21
+ 'Replaces the current additionalNotes field if provided.'),
22
+ },
23
+ annotations: { destructiveHint: false, idempotentHint: true, openWorldHint: false },
24
+ }, async ({ projectId, summary, additionalNotes }) => {
25
+ try {
26
+ // Validate non-empty summary
27
+ if (!summary.trim()) {
28
+ return errorResult('Summary text is required. Provide a non-empty summary of recent events or session state.');
29
+ }
30
+ const store = new FileProjectStore();
31
+ // Check project exists
32
+ const existing = await store.getById(projectId);
33
+ if (!existing) {
34
+ return errorResult(`Project not found: '${projectId}'. Use the project_list tool to see available projects and their IDs.`);
35
+ }
36
+ // Merge customData: preserve existing fields, overlay summary + optional additionalNotes
37
+ const mergedCustomData = {
38
+ ...existing.customData,
39
+ recentEvents: summary,
40
+ ...(additionalNotes !== undefined && { additionalNotes }),
41
+ };
42
+ await store.update(projectId, { customData: mergedCustomData });
43
+ // Read back updated project
44
+ const updated = await store.getById(projectId);
45
+ return jsonResult(updated);
46
+ }
47
+ catch (error) {
48
+ const message = error instanceof Error ? error.message : String(error);
49
+ return errorResult(`Error: ${message}`);
50
+ }
51
+ });
52
+ }
53
+ //# sourceMappingURL=stateTools.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"stateTools.js","sourceRoot":"","sources":["../../src/tools/stateTools.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AACxB,OAAO,EAAE,gBAAgB,EAAE,MAAM,0BAA0B,CAAC;AAC5D,OAAO,EAAE,WAAW,EAAE,UAAU,EAAE,MAAM,mBAAmB,CAAC;AAE5D,MAAM,UAAU,kBAAkB,CAAC,MAAiB;IAClD,4BAA4B;IAC5B,MAAM,CAAC,YAAY,CACjB,mBAAmB,EACnB;QACE,KAAK,EAAE,mBAAmB;QAC1B,WAAW,EACT,+GAA+G;YAC/G,iHAAiH;YACjH,0HAA0H;QAC5H,WAAW,EAAE;YACX,SAAS,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,CAAC,qDAAqD,CAAC;YACrF,OAAO,EAAE,CAAC;iBACP,MAAM,EAAE;iBACR,QAAQ,CACP,wEAAwE;gBACtE,kGAAkG,CACrG;YACH,eAAe,EAAE,CAAC;iBACf,MAAM,EAAE;iBACR,QAAQ,EAAE;iBACV,QAAQ,CACP,8DAA8D;gBAC5D,yDAAyD,CAC5D;SACJ;QACD,WAAW,EAAE,EAAE,eAAe,EAAE,KAAK,EAAE,cAAc,EAAE,IAAI,EAAE,aAAa,EAAE,KAAK,EAAE;KACpF,EACD,KAAK,EAAE,EAAE,SAAS,EAAE,OAAO,EAAE,eAAe,EAAE,EAAE,EAAE;QAChD,IAAI,CAAC;YACH,6BAA6B;YAC7B,IAAI,CAAC,OAAO,CAAC,IAAI,EAAE,EAAE,CAAC;gBACpB,OAAO,WAAW,CAChB,0FAA0F,CAC3F,CAAC;YACJ,CAAC;YAED,MAAM,KAAK,GAAG,IAAI,gBAAgB,EAAE,CAAC;YAErC,uBAAuB;YACvB,MAAM,QAAQ,GAAG,MAAM,KAAK,CAAC,OAAO,CAAC,SAAS,CAAC,CAAC;YAChD,IAAI,CAAC,QAAQ,EAAE,CAAC;gBACd,OAAO,WAAW,CAChB,uBAAuB,SAAS,uEAAuE,CACxG,CAAC;YACJ,CAAC;YAED,yFAAyF;YACzF,MAAM,gBAAgB,GAAG;gBACvB,GAAG,QAAQ,CAAC,UAAU;gBACtB,YAAY,EAAE,OAAO;gBACrB,GAAG,CAAC,eAAe,KAAK,SAAS,IAAI,EAAE,eAAe,EAAE,CAAC;aAC1D,CAAC;YAEF,MAAM,KAAK,CAAC,MAAM,CAAC,SAAS,EAAE,EAAE,UAAU,EAAE,gBAAgB,EAAE,CAAC,CAAC;YAEhE,4BAA4B;YAC5B,MAAM,OAAO,GAAG,MAAM,KAAK,CAAC,OAAO,CAAC,SAAS,CAAC,CAAC;YAC/C,OAAO,UAAU,CAAC,OAAO,CAAC,CAAC;QAC7B,CAAC;QAAC,OAAO,KAAc,EAAE,CAAC;YACxB,MAAM,OAAO,GAAG,KAAK,YAAY,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC;YACvE,OAAO,WAAW,CAAC,UAAU,OAAO,EAAE,CAAC,CAAC;QAC1C,CAAC;IACH,CAAC,CACF,CAAC;AACJ,CAAC"}
package/package.json ADDED
@@ -0,0 +1,51 @@
1
+ {
2
+ "name": "@context-forge/mcp",
3
+ "version": "0.1.0",
4
+ "description": "MCP server for Context Forge — generates structured AI context prompts from project configuration and templates",
5
+ "type": "module",
6
+ "main": "dist/index.js",
7
+ "bin": {
8
+ "context-forge-mcp": "./dist/index.js"
9
+ },
10
+ "files": [
11
+ "dist",
12
+ "README.md"
13
+ ],
14
+ "keywords": [
15
+ "mcp",
16
+ "context",
17
+ "ai",
18
+ "claude",
19
+ "cursor",
20
+ "prompt",
21
+ "context-forge"
22
+ ],
23
+ "author": "Manta Templates",
24
+ "license": "MIT",
25
+ "repository": {
26
+ "type": "git",
27
+ "url": "https://github.com/ecorkran/context-forge.git",
28
+ "directory": "packages/mcp-server"
29
+ },
30
+ "homepage": "https://github.com/ecorkran/context-forge/tree/main/packages/mcp-server#readme",
31
+ "engines": {
32
+ "node": ">=18.0.0"
33
+ },
34
+ "dependencies": {
35
+ "@modelcontextprotocol/sdk": "^1.26.0",
36
+ "zod": "^4.1.5",
37
+ "@context-forge/core": "0.1.0"
38
+ },
39
+ "devDependencies": {
40
+ "@types/node": "^25.3.0",
41
+ "typescript": "~5.8.3",
42
+ "vitest": "^3.2.1"
43
+ },
44
+ "scripts": {
45
+ "build": "tsc",
46
+ "dev": "tsc --watch",
47
+ "start": "node dist/index.js",
48
+ "test": "vitest run",
49
+ "typecheck": "tsc --noEmit"
50
+ }
51
+ }