brief-mcp 1.2.0 → 1.4.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.
Files changed (2) hide show
  1. package/dist/index.js +64 -23
  2. package/package.json +1 -1
package/dist/index.js CHANGED
@@ -41,28 +41,35 @@ class SupabaseClient {
41
41
  'Content-Type': 'application/json'
42
42
  };
43
43
  }
44
- async search(question) {
45
- const response = await axios.post(`${EDGE_FUNCTIONS_URL}/search-context`, { question, match_count: 5, match_threshold: 0.3 }, { headers: this.headers });
44
+ async search(question, orgRef) {
45
+ const response = await axios.post(`${EDGE_FUNCTIONS_URL}/search-context`, { question, match_count: 5, match_threshold: 0.3, org_ref: orgRef }, { headers: this.headers });
46
46
  return response.data;
47
47
  }
48
- async ingestDocument(content, title, orgId) {
49
- // First get user's org_id from a simple call
48
+ async ingestDocument(content, title, orgRef) {
50
49
  const response = await axios.post(`${EDGE_FUNCTIONS_URL}/ingest-context`, {
51
50
  content,
52
51
  title: title || 'Untitled',
53
- org_id: orgId,
52
+ org_ref: orgRef,
54
53
  source_type: 'mcp'
55
54
  }, { headers: this.headers });
56
55
  return response.data;
57
56
  }
58
- async listDocuments(limit = 20) {
59
- const response = await axios.get(`${EDGE_FUNCTIONS_URL}/list-documents?limit=${limit}`, { headers: this.headers });
57
+ async listDocuments(limit = 20, orgRef) {
58
+ let url = `${EDGE_FUNCTIONS_URL}/list-documents?limit=${limit}`;
59
+ if (orgRef) {
60
+ url += `&org_ref=${encodeURIComponent(orgRef)}`;
61
+ }
62
+ const response = await axios.get(url, { headers: this.headers });
60
63
  return response.data;
61
64
  }
62
65
  async deleteDocument(documentId) {
63
66
  const response = await axios.post(`${EDGE_FUNCTIONS_URL}/delete-document`, { document_id: documentId }, { headers: this.headers });
64
67
  return response.data;
65
68
  }
69
+ async listOrganizations() {
70
+ const response = await axios.get(`${EDGE_FUNCTIONS_URL}/list-organizations`, { headers: this.headers });
71
+ return response.data;
72
+ }
66
73
  }
67
74
  // ============================================================================
68
75
  // MCP Server
@@ -83,13 +90,17 @@ async function startMCPServer() {
83
90
  tools: [
84
91
  {
85
92
  name: 'search-context',
86
- description: 'Search your organization\'s knowledge base and get AI-powered answers. 8 models available: Mistral Small/Nemo, Llama 70B, Qwen 72B/Coder, DeepSeek V3, GLM, GPT-4o Mini.',
93
+ description: 'Search a knowledge base and get AI-powered answers. IMPORTANT: Call list-organizations first to get org_ref values, then specify which organization to search. If no org_ref is provided, uses your default organization.',
87
94
  inputSchema: {
88
95
  type: 'object',
89
96
  properties: {
90
97
  question: {
91
98
  type: 'string',
92
99
  description: 'Your question or search query'
100
+ },
101
+ org_ref: {
102
+ type: 'string',
103
+ description: 'Organization slug or ref to search in (from list-organizations). Required to search a specific org.'
93
104
  }
94
105
  },
95
106
  required: ['question']
@@ -97,7 +108,7 @@ async function startMCPServer() {
97
108
  },
98
109
  {
99
110
  name: 'add-knowledge',
100
- description: 'Add new content to your organization\'s knowledge base. Content is automatically chunked and vectorized.',
111
+ description: 'Add new content to a knowledge base. IMPORTANT: Call list-organizations first to get org_ref values if you want to add to a specific organization.',
101
112
  inputSchema: {
102
113
  type: 'object',
103
114
  properties: {
@@ -108,6 +119,10 @@ async function startMCPServer() {
108
119
  title: {
109
120
  type: 'string',
110
121
  description: 'Title for the document'
122
+ },
123
+ org_ref: {
124
+ type: 'string',
125
+ description: 'Organization slug or ref to add content to (from list-organizations)'
111
126
  }
112
127
  },
113
128
  required: ['content']
@@ -115,13 +130,17 @@ async function startMCPServer() {
115
130
  },
116
131
  {
117
132
  name: 'list-knowledge',
118
- description: 'List documents in your organization\'s knowledge base',
133
+ description: 'List documents in a knowledge base. IMPORTANT: Call list-organizations first to get org_ref values, then specify which organization to list. If no org_ref is provided, uses your default organization.',
119
134
  inputSchema: {
120
135
  type: 'object',
121
136
  properties: {
122
137
  limit: {
123
138
  type: 'number',
124
139
  description: 'Maximum number of documents to return (default: 20)'
140
+ },
141
+ org_ref: {
142
+ type: 'string',
143
+ description: 'Organization slug or ref to list documents from (from list-organizations). Required to list a specific org.'
125
144
  }
126
145
  }
127
146
  }
@@ -139,6 +158,14 @@ async function startMCPServer() {
139
158
  },
140
159
  required: ['id']
141
160
  }
161
+ },
162
+ {
163
+ name: 'list-organizations',
164
+ description: 'List all organizations you belong to, including your role and API key for each',
165
+ inputSchema: {
166
+ type: 'object',
167
+ properties: {}
168
+ }
142
169
  }
143
170
  ]
144
171
  }));
@@ -148,11 +175,11 @@ async function startMCPServer() {
148
175
  try {
149
176
  switch (name) {
150
177
  case 'search-context': {
151
- const { question } = toolArgs;
178
+ const { question, org_ref } = toolArgs;
152
179
  if (!question || typeof question !== 'string') {
153
180
  throw new Error('Question is required');
154
181
  }
155
- const result = await supabase.search(question);
182
+ const result = await supabase.search(question, org_ref);
156
183
  let responseText = result.answer;
157
184
  if (result.sources && result.sources.length > 0) {
158
185
  responseText += '\n\n---\n**Sources:**';
@@ -166,30 +193,26 @@ async function startMCPServer() {
166
193
  };
167
194
  }
168
195
  case 'add-knowledge': {
169
- const { content, title } = toolArgs;
196
+ const { content, title, org_ref } = toolArgs;
170
197
  if (!content || typeof content !== 'string') {
171
198
  throw new Error('Content is required');
172
199
  }
173
- // Get org_id from list-documents if not cached
174
- if (!cachedOrgId) {
175
- const listResult = await supabase.listDocuments(1);
176
- cachedOrgId = listResult.org_id;
177
- }
178
- const result = await supabase.ingestDocument(content, title, cachedOrgId);
200
+ const result = await supabase.ingestDocument(content, title, org_ref);
201
+ cachedOrgId = result.org_id; // Cache for future use
179
202
  return {
180
203
  content: [{
181
204
  type: 'text',
182
- text: `Document added!\nID: ${result.documentId}\nChunks created: ${result.chunks}`
205
+ text: `Document added!\nID: ${result.documentId}\nChunks created: ${result.chunks}${org_ref ? `\nOrganization: ${org_ref}` : ''}`
183
206
  }]
184
207
  };
185
208
  }
186
209
  case 'list-knowledge': {
187
- const { limit } = toolArgs;
188
- const result = await supabase.listDocuments(limit || 20);
210
+ const { limit, org_ref } = toolArgs;
211
+ const result = await supabase.listDocuments(limit || 20, org_ref);
189
212
  cachedOrgId = result.org_id; // Cache for future add-knowledge calls
190
213
  if (result.documents.length === 0) {
191
214
  return {
192
- content: [{ type: 'text', text: 'No documents in knowledge base.' }]
215
+ content: [{ type: 'text', text: `No documents in knowledge base${org_ref ? ` (org: ${org_ref})` : ''}.` }]
193
216
  };
194
217
  }
195
218
  let text = `**${result.documents.length} document(s):**\n\n`;
@@ -216,6 +239,24 @@ async function startMCPServer() {
216
239
  }]
217
240
  };
218
241
  }
242
+ case 'list-organizations': {
243
+ const result = await supabase.listOrganizations();
244
+ if (result.organizations.length === 0) {
245
+ return {
246
+ content: [{ type: 'text', text: 'You are not a member of any organization.' }]
247
+ };
248
+ }
249
+ let text = `**${result.total_count} organization(s):**\n\n`;
250
+ result.organizations.forEach((org, i) => {
251
+ const defaultMark = org.is_default ? ' ⭐ (default)' : '';
252
+ text += `${i + 1}. **${org.name}**${defaultMark}\n`;
253
+ text += ` Slug: \`${org.slug}\` | Role: ${org.role} | Members: ${org.member_count}\n`;
254
+ text += ` API Key: \`${org.api_key}\`\n\n`;
255
+ });
256
+ return {
257
+ content: [{ type: 'text', text }]
258
+ };
259
+ }
219
260
  default:
220
261
  throw new Error(`Unknown tool: ${name}`);
221
262
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "brief-mcp",
3
- "version": "1.2.0",
3
+ "version": "1.4.0",
4
4
  "description": "Brief MCP - Context-first development with RAG-powered knowledge base",
5
5
  "type": "module",
6
6
  "main": "dist/index.js",