@contextstream/mcp-server 0.2.5

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/src/prompts.ts ADDED
@@ -0,0 +1,308 @@
1
+ import type { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';
2
+ import { z } from 'zod';
3
+
4
+ export function registerPrompts(server: McpServer) {
5
+ // Code exploration prompt
6
+ server.registerPrompt(
7
+ 'explore-codebase',
8
+ {
9
+ title: 'Explore Codebase',
10
+ description: 'Get an overview of a project codebase structure and key components',
11
+ argsSchema: {
12
+ project_id: z.string().uuid().describe('Project ID to explore'),
13
+ focus_area: z.string().optional().describe('Optional area to focus on (e.g., "authentication", "api routes")'),
14
+ },
15
+ },
16
+ async (args) => ({
17
+ messages: [
18
+ {
19
+ role: 'user',
20
+ content: {
21
+ type: 'text',
22
+ text: `I want to understand the codebase for project ${args.project_id}${args.focus_area ? ` with focus on ${args.focus_area}` : ''}.
23
+
24
+ Please help me by:
25
+ 1. First, use \`projects.overview\` to get the project summary
26
+ 2. Use \`projects.files\` to list the key files
27
+ 3. Use \`search.semantic\` to find relevant code${args.focus_area ? ` related to "${args.focus_area}"` : ''}
28
+ 4. Summarize the architecture and key patterns you observe
29
+
30
+ Provide a clear, structured overview that helps me navigate this codebase effectively.`,
31
+ },
32
+ },
33
+ ],
34
+ })
35
+ );
36
+
37
+ // Memory capture prompt
38
+ server.registerPrompt(
39
+ 'capture-decision',
40
+ {
41
+ title: 'Capture Decision',
42
+ description: 'Document an architectural or technical decision in workspace memory',
43
+ argsSchema: {
44
+ workspace_id: z.string().uuid().describe('Workspace ID'),
45
+ decision_title: z.string().describe('Brief title of the decision'),
46
+ context: z.string().describe('What prompted this decision'),
47
+ decision: z.string().describe('The decision made'),
48
+ consequences: z.string().optional().describe('Expected consequences or tradeoffs'),
49
+ },
50
+ },
51
+ async (args) => ({
52
+ messages: [
53
+ {
54
+ role: 'user',
55
+ content: {
56
+ type: 'text',
57
+ text: `Please document the following decision in workspace memory:
58
+
59
+ **Title:** ${args.decision_title}
60
+ **Context:** ${args.context}
61
+ **Decision:** ${args.decision}
62
+ ${args.consequences ? `**Consequences:** ${args.consequences}` : ''}
63
+
64
+ Use \`memory.create_event\` with:
65
+ - event_type: "decision"
66
+ - workspace_id: "${args.workspace_id}"
67
+ - title: The decision title
68
+ - content: A well-formatted ADR (Architecture Decision Record) with context, decision, and consequences
69
+ - metadata: Include relevant tags and status
70
+
71
+ After creating, confirm the decision was recorded and summarize it.`,
72
+ },
73
+ },
74
+ ],
75
+ })
76
+ );
77
+
78
+ // Code review context prompt
79
+ server.registerPrompt(
80
+ 'review-context',
81
+ {
82
+ title: 'Code Review Context',
83
+ description: 'Build context for reviewing code changes',
84
+ argsSchema: {
85
+ project_id: z.string().uuid().describe('Project ID'),
86
+ file_paths: z.string().describe('Comma-separated file paths being changed'),
87
+ change_description: z.string().describe('Brief description of the changes'),
88
+ },
89
+ },
90
+ async (args) => ({
91
+ messages: [
92
+ {
93
+ role: 'user',
94
+ content: {
95
+ type: 'text',
96
+ text: `I need context to review changes in these files: ${args.file_paths}
97
+
98
+ Change description: ${args.change_description}
99
+
100
+ Please help me understand the impact by:
101
+ 1. Use \`graph.dependencies\` to find what depends on these files
102
+ 2. Use \`graph.impact\` to analyze potential impact
103
+ 3. Use \`memory.search\` to find related decisions or notes about these areas
104
+ 4. Use \`search.semantic\` to find related code patterns
105
+
106
+ Provide:
107
+ - Summary of what these files do
108
+ - What other parts of the codebase might be affected
109
+ - Any relevant past decisions or context from memory
110
+ - Potential risks or areas to focus the review on`,
111
+ },
112
+ },
113
+ ],
114
+ })
115
+ );
116
+
117
+ // Debug investigation prompt
118
+ server.registerPrompt(
119
+ 'investigate-bug',
120
+ {
121
+ title: 'Investigate Bug',
122
+ description: 'Build context for debugging an issue',
123
+ argsSchema: {
124
+ project_id: z.string().uuid().describe('Project ID'),
125
+ error_message: z.string().describe('Error message or symptom'),
126
+ affected_area: z.string().optional().describe('Known affected area or component'),
127
+ },
128
+ },
129
+ async (args) => ({
130
+ messages: [
131
+ {
132
+ role: 'user',
133
+ content: {
134
+ type: 'text',
135
+ text: `I'm investigating a bug:
136
+
137
+ **Error/Symptom:** ${args.error_message}
138
+ ${args.affected_area ? `**Affected Area:** ${args.affected_area}` : ''}
139
+
140
+ Please help me investigate by:
141
+ 1. Use \`search.semantic\` to find code related to this error
142
+ 2. Use \`search.pattern\` to find where similar errors are thrown
143
+ 3. Use \`graph.call_path\` to trace call flows if we identify key functions
144
+ 4. Use \`memory.search\` to check if this issue has been encountered before
145
+
146
+ Provide:
147
+ - Likely locations where this error originates
148
+ - Call flow analysis
149
+ - Any related past issues from memory
150
+ - Suggested debugging approach`,
151
+ },
152
+ },
153
+ ],
154
+ })
155
+ );
156
+
157
+ // Knowledge graph exploration prompt
158
+ server.registerPrompt(
159
+ 'explore-knowledge',
160
+ {
161
+ title: 'Explore Knowledge Graph',
162
+ description: 'Navigate and understand the knowledge graph for a workspace',
163
+ argsSchema: {
164
+ workspace_id: z.string().uuid().describe('Workspace ID'),
165
+ starting_topic: z.string().optional().describe('Topic to start exploration from'),
166
+ },
167
+ },
168
+ async (args) => ({
169
+ messages: [
170
+ {
171
+ role: 'user',
172
+ content: {
173
+ type: 'text',
174
+ text: `Help me explore the knowledge captured in workspace ${args.workspace_id}${args.starting_topic ? ` starting from "${args.starting_topic}"` : ''}.
175
+
176
+ Please:
177
+ 1. Use \`memory.list_nodes\` to see available knowledge nodes
178
+ 2. Use \`memory.decisions\` to see decision history
179
+ 3. ${args.starting_topic ? `Use \`memory.search\` to find nodes related to "${args.starting_topic}"` : 'Use \`memory.summary\` to get an overview'}
180
+ 4. Use \`graph.related\` to explore connections between nodes
181
+
182
+ Provide:
183
+ - Overview of knowledge captured
184
+ - Key themes and topics
185
+ - Important decisions and their rationale
186
+ - Connections between different pieces of knowledge`,
187
+ },
188
+ },
189
+ ],
190
+ })
191
+ );
192
+
193
+ // Onboarding context prompt
194
+ server.registerPrompt(
195
+ 'onboard-to-project',
196
+ {
197
+ title: 'Project Onboarding',
198
+ description: 'Generate onboarding context for a new team member',
199
+ argsSchema: {
200
+ project_id: z.string().uuid().describe('Project ID'),
201
+ workspace_id: z.string().uuid().describe('Workspace ID'),
202
+ role: z.string().optional().describe('Role of the person being onboarded (e.g., "backend developer", "frontend developer")'),
203
+ },
204
+ },
205
+ async (args) => ({
206
+ messages: [
207
+ {
208
+ role: 'user',
209
+ content: {
210
+ type: 'text',
211
+ text: `Create an onboarding guide for a new team member joining this project.
212
+ ${args.role ? `They will be working as a ${args.role}.` : ''}
213
+
214
+ Please gather comprehensive context:
215
+ 1. Use \`projects.overview\` and \`projects.statistics\` for project summary
216
+ 2. Use \`projects.files\` to identify key entry points
217
+ 3. Use \`memory.timeline\` to see recent activity and changes
218
+ 4. Use \`memory.decisions\` to understand key architectural choices
219
+ 5. Use \`search.semantic\` to find documentation and READMEs
220
+
221
+ Provide an onboarding guide that includes:
222
+ - Project overview and purpose
223
+ - Technology stack and architecture
224
+ - Key files and entry points${args.role ? ` relevant to ${args.role}` : ''}
225
+ - Important decisions and their rationale
226
+ - Recent changes and current focus areas
227
+ - Getting started steps`,
228
+ },
229
+ },
230
+ ],
231
+ })
232
+ );
233
+
234
+ // Refactoring analysis prompt
235
+ server.registerPrompt(
236
+ 'analyze-refactoring',
237
+ {
238
+ title: 'Refactoring Analysis',
239
+ description: 'Analyze a codebase for refactoring opportunities',
240
+ argsSchema: {
241
+ project_id: z.string().uuid().describe('Project ID'),
242
+ target_area: z.string().optional().describe('Specific area to analyze'),
243
+ },
244
+ },
245
+ async (args) => ({
246
+ messages: [
247
+ {
248
+ role: 'user',
249
+ content: {
250
+ type: 'text',
251
+ text: `Analyze the codebase for refactoring opportunities${args.target_area ? ` in ${args.target_area}` : ''}.
252
+
253
+ Please investigate:
254
+ 1. Use \`graph.circular_dependencies\` to find circular dependencies
255
+ 2. Use \`graph.unused_code\` to find dead code
256
+ 3. Use \`search.pattern\` to find code duplication patterns
257
+ 4. Use \`projects.statistics\` to identify complex areas
258
+
259
+ Provide:
260
+ - Circular dependencies that should be broken
261
+ - Unused code that can be removed
262
+ - Duplicate patterns that could be consolidated
263
+ - High complexity areas that need simplification
264
+ - Prioritized refactoring recommendations`,
265
+ },
266
+ },
267
+ ],
268
+ })
269
+ );
270
+
271
+ // AI context building prompt
272
+ server.registerPrompt(
273
+ 'build-context',
274
+ {
275
+ title: 'Build LLM Context',
276
+ description: 'Build comprehensive context for an LLM task',
277
+ argsSchema: {
278
+ query: z.string().describe('What you need context for'),
279
+ workspace_id: z.string().uuid().optional().describe('Workspace ID'),
280
+ project_id: z.string().uuid().optional().describe('Project ID'),
281
+ include_memory: z.string().optional().describe('Include memory/decisions ("true" or "false")'),
282
+ },
283
+ },
284
+ async (args) => ({
285
+ messages: [
286
+ {
287
+ role: 'user',
288
+ content: {
289
+ type: 'text',
290
+ text: `Build comprehensive context for the following task:
291
+
292
+ **Query:** ${args.query}
293
+
294
+ Please use \`ai.enhanced_context\` with:
295
+ - query: "${args.query}"
296
+ ${args.workspace_id ? `- workspace_id: "${args.workspace_id}"` : ''}
297
+ ${args.project_id ? `- project_id: "${args.project_id}"` : ''}
298
+ - include_code: true
299
+ - include_docs: true
300
+ - include_memory: ${args.include_memory ?? true}
301
+
302
+ Then synthesize the retrieved context into a coherent briefing that will help with the task.`,
303
+ },
304
+ },
305
+ ],
306
+ })
307
+ );
308
+ }
@@ -0,0 +1,49 @@
1
+ import { ResourceTemplate } from '@modelcontextprotocol/sdk/server/mcp.js';
2
+ import type { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';
3
+ import type { ContextStreamClient } from './client.js';
4
+
5
+ function wrapText(uri: string, text: string) {
6
+ return { contents: [{ uri, text }] };
7
+ }
8
+
9
+ export function registerResources(server: McpServer, client: ContextStreamClient, apiUrl: string) {
10
+ // OpenAPI resource
11
+ server.registerResource(
12
+ 'contextstream-openapi',
13
+ new ResourceTemplate('contextstream:openapi', { list: undefined }),
14
+ {
15
+ title: 'ContextStream OpenAPI spec',
16
+ description: 'Machine-readable OpenAPI from the configured API endpoint',
17
+ mimeType: 'application/json',
18
+ },
19
+ async () => {
20
+ const uri = `${apiUrl.replace(/\/$/, '')}/api-docs/openapi.json`;
21
+ const res = await fetch(uri);
22
+ const text = await res.text();
23
+ return wrapText('contextstream:openapi', text);
24
+ }
25
+ );
26
+
27
+ // Workspaces list resource
28
+ server.registerResource(
29
+ 'contextstream-workspaces',
30
+ new ResourceTemplate('contextstream:workspaces', { list: undefined }),
31
+ { title: 'Workspaces', description: 'List of accessible workspaces' },
32
+ async () => {
33
+ const data = await client.listWorkspaces();
34
+ return wrapText('contextstream:workspaces', JSON.stringify(data, null, 2));
35
+ }
36
+ );
37
+
38
+ // Projects by workspace resource template
39
+ server.registerResource(
40
+ 'contextstream-projects',
41
+ new ResourceTemplate('contextstream:projects/{workspaceId}', { list: undefined }),
42
+ { title: 'Projects for workspace', description: 'Projects in the specified workspace' },
43
+ async (uri, { workspaceId }) => {
44
+ const wsId = Array.isArray(workspaceId) ? workspaceId[0] : workspaceId;
45
+ const data = await client.listProjects({ workspace_id: wsId });
46
+ return wrapText(uri.href, JSON.stringify(data, null, 2));
47
+ }
48
+ );
49
+ }