ai-context-sync-mcp 1.0.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/.env ADDED
@@ -0,0 +1,3 @@
1
+ # MCP Server Configuration
2
+ CONTEXT_SYNC_API_KEY=your-api-key-here
3
+ CONTEXT_SYNC_BACKEND_URL=http://localhost:8000
package/.env.example ADDED
@@ -0,0 +1,3 @@
1
+ # MCP Server Configuration
2
+ CONTEXT_SYNC_API_KEY=your-api-key-here
3
+ CONTEXT_SYNC_BACKEND_URL=http://localhost:8000
package/build/index.js ADDED
@@ -0,0 +1,219 @@
1
+ #!/usr/bin/env node
2
+ import { Server } from "@modelcontextprotocol/sdk/server/index.js";
3
+ import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js";
4
+ import { CallToolRequestSchema, ListToolsRequestSchema, } from "@modelcontextprotocol/sdk/types.js";
5
+ import dotenv from "dotenv";
6
+ import path from "path";
7
+ dotenv.config();
8
+ const API_KEY = process.env.CONTEXT_SYNC_API_KEY;
9
+ const BACKEND_URL = process.env.CONTEXT_SYNC_BACKEND_URL || "http://127.0.0.1:8000";
10
+ const CLIENT_INFO = process.env.CONTEXT_SYNC_CLIENT || "MCP Server";
11
+ if (!API_KEY) {
12
+ console.error("Warning: CONTEXT_SYNC_API_KEY environment variable is not set. MCP tools will fail authorization check.");
13
+ }
14
+ const server = new Server({
15
+ name: "context-sync-mcp",
16
+ version: "1.0.0",
17
+ }, {
18
+ capabilities: {
19
+ tools: {},
20
+ },
21
+ });
22
+ // Register available tools
23
+ server.setRequestHandler(ListToolsRequestSchema, async () => {
24
+ return {
25
+ tools: [
26
+ {
27
+ name: "push_context",
28
+ description: "Save a new chat context, summary, or feature description to the Context-Sync backend so it can be restored or queried later.",
29
+ inputSchema: {
30
+ type: "object",
31
+ properties: {
32
+ projectName: {
33
+ type: "string",
34
+ description: "The name of the project this context belongs to."
35
+ },
36
+ contextName: {
37
+ type: "string",
38
+ description: "A short descriptive name for this context block (e.g. 'auth-logic', 'main-db-schema')."
39
+ },
40
+ contextDescription: {
41
+ type: "string",
42
+ description: "A detailed explanation of what this context is about, helping semantic search locate it later."
43
+ },
44
+ contextData: {
45
+ type: "string",
46
+ description: "The actual code context, chat history, or serialized message transcripts to save."
47
+ },
48
+ contextType: {
49
+ type: "string",
50
+ enum: ["full", "summary", "feature"],
51
+ description: "The type of context being saved."
52
+ }
53
+ },
54
+ required: ["contextData"]
55
+ }
56
+ },
57
+ {
58
+ name: "pull_context",
59
+ description: "Retrieve a saved chat context, summary, or feature description from the Context-Sync backend by searching for it.",
60
+ inputSchema: {
61
+ type: "object",
62
+ properties: {
63
+ searchQuery: {
64
+ type: "string",
65
+ description: "Describe what context you need (e.g. 'how did we setup JWT authentication?')."
66
+ },
67
+ projectName: {
68
+ type: "string",
69
+ description: "Optional. Restrict search to this specific project name."
70
+ }
71
+ },
72
+ required: ["searchQuery"]
73
+ }
74
+ }
75
+ ]
76
+ };
77
+ });
78
+ // Handle tool execution requests
79
+ server.setRequestHandler(CallToolRequestSchema, async (request) => {
80
+ const { name, arguments: args } = request.params;
81
+ if (!API_KEY) {
82
+ return {
83
+ content: [
84
+ {
85
+ type: "text",
86
+ text: "Error: CONTEXT_SYNC_API_KEY environment variable is missing on the MCP server. Configure it with your API key from the web dashboard.",
87
+ },
88
+ ],
89
+ isError: true,
90
+ };
91
+ }
92
+ if (name === "push_context") {
93
+ const { projectName, contextName, contextDescription, contextData, contextType } = args;
94
+ // Resolve fallbacks for optional parameters
95
+ const defaultProject = path.basename(process.cwd()) || "default-project";
96
+ const resolvedProjectName = projectName || defaultProject;
97
+ const timestamp = new Date().toISOString().slice(0, 10);
98
+ const resolvedContextName = contextName || `session-${timestamp}`;
99
+ const resolvedContextDescription = contextDescription || "Automatically synchronized development context block.";
100
+ const resolvedContextType = contextType || "full";
101
+ try {
102
+ const response = await fetch(`${BACKEND_URL}/api/mcp/push`, {
103
+ method: "POST",
104
+ headers: {
105
+ "Content-Type": "application/json",
106
+ "X-API-Key": API_KEY,
107
+ "X-Client-Info": CLIENT_INFO,
108
+ },
109
+ body: JSON.stringify({
110
+ project_name: resolvedProjectName,
111
+ context_name: resolvedContextName,
112
+ context_description: resolvedContextDescription,
113
+ context_data: contextData,
114
+ type: resolvedContextType,
115
+ }),
116
+ });
117
+ if (!response.ok) {
118
+ const errData = await response.json().catch(() => ({ detail: "Unknown backend error" }));
119
+ return {
120
+ content: [
121
+ {
122
+ type: "text",
123
+ text: `Failed to push context: ${errData.detail || response.statusText}`,
124
+ },
125
+ ],
126
+ isError: true,
127
+ };
128
+ }
129
+ const result = await response.json();
130
+ return {
131
+ content: [
132
+ {
133
+ type: "text",
134
+ text: `Successfully pushed context '${resolvedContextName}' to project '${resolvedProjectName}'! Size: ${contextData.length} characters.`,
135
+ },
136
+ ],
137
+ };
138
+ }
139
+ catch (error) {
140
+ return {
141
+ content: [
142
+ {
143
+ type: "text",
144
+ text: `Network error connecting to backend: ${error.message}`,
145
+ },
146
+ ],
147
+ isError: true,
148
+ };
149
+ }
150
+ }
151
+ if (name === "pull_context") {
152
+ const { searchQuery, projectName } = args;
153
+ try {
154
+ const response = await fetch(`${BACKEND_URL}/api/mcp/pull`, {
155
+ method: "POST",
156
+ headers: {
157
+ "Content-Type": "application/json",
158
+ "X-API-Key": API_KEY,
159
+ "X-Client-Info": CLIENT_INFO,
160
+ },
161
+ body: JSON.stringify({
162
+ search_query: searchQuery,
163
+ project_name: projectName || null,
164
+ }),
165
+ });
166
+ if (!response.ok) {
167
+ const errData = await response.json().catch(() => ({ detail: "Unknown backend error" }));
168
+ return {
169
+ content: [
170
+ {
171
+ type: "text",
172
+ text: `Failed to pull context: ${errData.detail || response.statusText}`,
173
+ },
174
+ ],
175
+ isError: true,
176
+ };
177
+ }
178
+ const result = await response.json();
179
+ return {
180
+ content: [
181
+ {
182
+ type: "text",
183
+ text: `Successfully retrieved matching context!\n\n` +
184
+ `Project: ${result.project_name}\n` +
185
+ `Context Name: ${result.name}\n` +
186
+ `Description: ${result.description}\n` +
187
+ `Type: ${result.type}\n` +
188
+ `Last Updated: ${result.updated_at}\n\n` +
189
+ `--- CONTEXT DATA ---\n` +
190
+ `${result.context_data}\n` +
191
+ `-------------------`
192
+ },
193
+ ],
194
+ };
195
+ }
196
+ catch (error) {
197
+ return {
198
+ content: [
199
+ {
200
+ type: "text",
201
+ text: `Network error connecting to backend: ${error.message}`,
202
+ },
203
+ ],
204
+ isError: true,
205
+ };
206
+ }
207
+ }
208
+ throw new Error(`Tool not found: ${name}`);
209
+ });
210
+ // Run server on stdio transport
211
+ async function run() {
212
+ const transport = new StdioServerTransport();
213
+ await server.connect(transport);
214
+ console.error("Context-Sync MCP Server running on stdio transport");
215
+ }
216
+ run().catch((error) => {
217
+ console.error("Fatal error running MCP server:", error);
218
+ process.exit(1);
219
+ });
package/package.json ADDED
@@ -0,0 +1,23 @@
1
+ {
2
+ "name": "ai-context-sync-mcp",
3
+ "version": "1.0.0",
4
+ "description": "Model Context Protocol Server for Context-Sync-MCP",
5
+ "type": "module",
6
+ "main": "build/index.js",
7
+ "bin": {
8
+ "ai-context-sync-mcp": "./build/index.js"
9
+ },
10
+ "scripts": {
11
+ "build": "tsc",
12
+ "start": "node build/index.js",
13
+ "prepare": "npm run build"
14
+ },
15
+ "dependencies": {
16
+ "@modelcontextprotocol/sdk": "^0.6.0",
17
+ "dotenv": "^16.4.5"
18
+ },
19
+ "devDependencies": {
20
+ "@types/node": "^20.11.24",
21
+ "typescript": "^5.3.3"
22
+ }
23
+ }
package/src/index.ts ADDED
@@ -0,0 +1,243 @@
1
+ #!/usr/bin/env node
2
+ import { Server } from "@modelcontextprotocol/sdk/server/index.js";
3
+ import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js";
4
+ import {
5
+ CallToolRequestSchema,
6
+ ListToolsRequestSchema,
7
+ } from "@modelcontextprotocol/sdk/types.js";
8
+ import dotenv from "dotenv";
9
+ import path from "path";
10
+
11
+ dotenv.config();
12
+
13
+ const API_KEY = process.env.CONTEXT_SYNC_API_KEY;
14
+ const BACKEND_URL = process.env.CONTEXT_SYNC_BACKEND_URL || "http://127.0.0.1:8000";
15
+ const CLIENT_INFO = process.env.CONTEXT_SYNC_CLIENT || "MCP Server";
16
+
17
+ if (!API_KEY) {
18
+ console.error("Warning: CONTEXT_SYNC_API_KEY environment variable is not set. MCP tools will fail authorization check.");
19
+ }
20
+
21
+ const server = new Server(
22
+ {
23
+ name: "context-sync-mcp",
24
+ version: "1.0.0",
25
+ },
26
+ {
27
+ capabilities: {
28
+ tools: {},
29
+ },
30
+ }
31
+ );
32
+
33
+ // Register available tools
34
+ server.setRequestHandler(ListToolsRequestSchema, async () => {
35
+ return {
36
+ tools: [
37
+ {
38
+ name: "push_context",
39
+ description: "Save a new chat context, summary, or feature description to the Context-Sync backend so it can be restored or queried later.",
40
+ inputSchema: {
41
+ type: "object",
42
+ properties: {
43
+ projectName: {
44
+ type: "string",
45
+ description: "The name of the project this context belongs to."
46
+ },
47
+ contextName: {
48
+ type: "string",
49
+ description: "A short descriptive name for this context block (e.g. 'auth-logic', 'main-db-schema')."
50
+ },
51
+ contextDescription: {
52
+ type: "string",
53
+ description: "A detailed explanation of what this context is about, helping semantic search locate it later."
54
+ },
55
+ contextData: {
56
+ type: "string",
57
+ description: "The actual code context, chat history, or serialized message transcripts to save."
58
+ },
59
+ contextType: {
60
+ type: "string",
61
+ enum: ["full", "summary", "feature"],
62
+ description: "The type of context being saved."
63
+ }
64
+ },
65
+ required: ["contextData"]
66
+ }
67
+ },
68
+ {
69
+ name: "pull_context",
70
+ description: "Retrieve a saved chat context, summary, or feature description from the Context-Sync backend by searching for it.",
71
+ inputSchema: {
72
+ type: "object",
73
+ properties: {
74
+ searchQuery: {
75
+ type: "string",
76
+ description: "Describe what context you need (e.g. 'how did we setup JWT authentication?')."
77
+ },
78
+ projectName: {
79
+ type: "string",
80
+ description: "Optional. Restrict search to this specific project name."
81
+ }
82
+ },
83
+ required: ["searchQuery"]
84
+ }
85
+ }
86
+ ]
87
+ };
88
+ });
89
+
90
+ // Handle tool execution requests
91
+ server.setRequestHandler(CallToolRequestSchema, async (request) => {
92
+ const { name, arguments: args } = request.params;
93
+
94
+ if (!API_KEY) {
95
+ return {
96
+ content: [
97
+ {
98
+ type: "text",
99
+ text: "Error: CONTEXT_SYNC_API_KEY environment variable is missing on the MCP server. Configure it with your API key from the web dashboard.",
100
+ },
101
+ ],
102
+ isError: true,
103
+ };
104
+ }
105
+
106
+ if (name === "push_context") {
107
+ const { projectName, contextName, contextDescription, contextData, contextType } = args as any;
108
+
109
+ // Resolve fallbacks for optional parameters
110
+ const defaultProject = path.basename(process.cwd()) || "default-project";
111
+ const resolvedProjectName = projectName || defaultProject;
112
+
113
+ const timestamp = new Date().toISOString().slice(0, 10);
114
+ const resolvedContextName = contextName || `session-${timestamp}`;
115
+
116
+ const resolvedContextDescription = contextDescription || "Automatically synchronized development context block.";
117
+ const resolvedContextType = contextType || "full";
118
+
119
+ try {
120
+ const response = await fetch(`${BACKEND_URL}/api/mcp/push`, {
121
+ method: "POST",
122
+ headers: {
123
+ "Content-Type": "application/json",
124
+ "X-API-Key": API_KEY,
125
+ "X-Client-Info": CLIENT_INFO,
126
+ },
127
+ body: JSON.stringify({
128
+ project_name: resolvedProjectName,
129
+ context_name: resolvedContextName,
130
+ context_description: resolvedContextDescription,
131
+ context_data: contextData,
132
+ type: resolvedContextType,
133
+ }),
134
+ });
135
+
136
+ if (!response.ok) {
137
+ const errData = await response.json().catch(() => ({ detail: "Unknown backend error" }));
138
+ return {
139
+ content: [
140
+ {
141
+ type: "text",
142
+ text: `Failed to push context: ${errData.detail || response.statusText}`,
143
+ },
144
+ ],
145
+ isError: true,
146
+ };
147
+ }
148
+
149
+ const result = await response.json();
150
+ return {
151
+ content: [
152
+ {
153
+ type: "text",
154
+ text: `Successfully pushed context '${resolvedContextName}' to project '${resolvedProjectName}'! Size: ${contextData.length} characters.`,
155
+ },
156
+ ],
157
+ };
158
+ } catch (error: any) {
159
+ return {
160
+ content: [
161
+ {
162
+ type: "text",
163
+ text: `Network error connecting to backend: ${error.message}`,
164
+ },
165
+ ],
166
+ isError: true,
167
+ };
168
+ }
169
+ }
170
+
171
+ if (name === "pull_context") {
172
+ const { searchQuery, projectName } = args as any;
173
+ try {
174
+ const response = await fetch(`${BACKEND_URL}/api/mcp/pull`, {
175
+ method: "POST",
176
+ headers: {
177
+ "Content-Type": "application/json",
178
+ "X-API-Key": API_KEY,
179
+ "X-Client-Info": CLIENT_INFO,
180
+ },
181
+ body: JSON.stringify({
182
+ search_query: searchQuery,
183
+ project_name: projectName || null,
184
+ }),
185
+ });
186
+
187
+ if (!response.ok) {
188
+ const errData = await response.json().catch(() => ({ detail: "Unknown backend error" }));
189
+ return {
190
+ content: [
191
+ {
192
+ type: "text",
193
+ text: `Failed to pull context: ${errData.detail || response.statusText}`,
194
+ },
195
+ ],
196
+ isError: true,
197
+ };
198
+ }
199
+
200
+ const result: any = await response.json();
201
+ return {
202
+ content: [
203
+ {
204
+ type: "text",
205
+ text: `Successfully retrieved matching context!\n\n` +
206
+ `Project: ${result.project_name}\n` +
207
+ `Context Name: ${result.name}\n` +
208
+ `Description: ${result.description}\n` +
209
+ `Type: ${result.type}\n` +
210
+ `Last Updated: ${result.updated_at}\n\n` +
211
+ `--- CONTEXT DATA ---\n` +
212
+ `${result.context_data}\n` +
213
+ `-------------------`
214
+ },
215
+ ],
216
+ };
217
+ } catch (error: any) {
218
+ return {
219
+ content: [
220
+ {
221
+ type: "text",
222
+ text: `Network error connecting to backend: ${error.message}`,
223
+ },
224
+ ],
225
+ isError: true,
226
+ };
227
+ }
228
+ }
229
+
230
+ throw new Error(`Tool not found: ${name}`);
231
+ });
232
+
233
+ // Run server on stdio transport
234
+ async function run() {
235
+ const transport = new StdioServerTransport();
236
+ await server.connect(transport);
237
+ console.error("Context-Sync MCP Server running on stdio transport");
238
+ }
239
+
240
+ run().catch((error) => {
241
+ console.error("Fatal error running MCP server:", error);
242
+ process.exit(1);
243
+ });
package/tsconfig.json ADDED
@@ -0,0 +1,14 @@
1
+ {
2
+ "compilerOptions": {
3
+ "target": "ES2022",
4
+ "module": "NodeNext",
5
+ "moduleResolution": "NodeNext",
6
+ "outDir": "./build",
7
+ "rootDir": "./src",
8
+ "strict": true,
9
+ "esModuleInterop": true,
10
+ "skipLibCheck": true,
11
+ "forceConsistentCasingInFileNames": true
12
+ },
13
+ "include": ["src/**/*"]
14
+ }