parisinnov-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/README.md ADDED
@@ -0,0 +1,50 @@
1
+ # parisinnov-mcp
2
+
3
+ MCP Server for RAG-powered knowledge base with **GLM-4.7**.
4
+
5
+ ## Quick Start
6
+
7
+ ### Claude Code
8
+
9
+ Add to `~/.claude/claude_desktop_config.json`:
10
+
11
+ ```json
12
+ {
13
+ "mcpServers": {
14
+ "parisinnov": {
15
+ "command": "npx",
16
+ "args": [
17
+ "parisinnov-mcp",
18
+ "--access-token", "your_api_key"
19
+ ]
20
+ }
21
+ }
22
+ }
23
+ ```
24
+
25
+ **Windows:** `%APPDATA%\Claude\claude_desktop_config.json`
26
+
27
+ ### Cursor
28
+
29
+ Same config format in Cursor MCP settings.
30
+
31
+ ## That's it!
32
+
33
+ No installation needed. `npx` handles everything.
34
+
35
+ ## Tools
36
+
37
+ | Tool | Description |
38
+ |------|-------------|
39
+ | `search-context` | Search knowledge base with AI answers (GLM-4.7) |
40
+ | `add-knowledge` | Add document to knowledge base |
41
+ | `list-knowledge` | List all documents |
42
+ | `delete-knowledge` | Delete a document |
43
+
44
+ ## Get your API key
45
+
46
+ Contact the Paris Innov team to get your access token.
47
+
48
+ ## License
49
+
50
+ MIT
@@ -0,0 +1,2 @@
1
+ #!/usr/bin/env node
2
+ export {};
package/dist/index.js ADDED
@@ -0,0 +1,249 @@
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 axios from 'axios';
6
+ import yargs from 'yargs';
7
+ import { hideBin } from 'yargs/helpers';
8
+ // ============================================================================
9
+ // Configuration
10
+ // ============================================================================
11
+ const BACKEND_URL = 'https://parisinnovbackend-production.up.railway.app';
12
+ function parseArguments() {
13
+ const argv = yargs(hideBin(process.argv))
14
+ .option('access-token', {
15
+ alias: 't',
16
+ type: 'string',
17
+ description: 'API key for backend authentication',
18
+ demandOption: true
19
+ })
20
+ .help()
21
+ .parseSync();
22
+ return {
23
+ accessToken: argv['access-token']
24
+ };
25
+ }
26
+ // ============================================================================
27
+ // Backend API Client
28
+ // ============================================================================
29
+ class BackendClient {
30
+ accessToken;
31
+ constructor(accessToken) {
32
+ this.accessToken = accessToken;
33
+ }
34
+ get headers() {
35
+ return {
36
+ 'Authorization': `Bearer ${this.accessToken}`,
37
+ 'Content-Type': 'application/json'
38
+ };
39
+ }
40
+ async ask(question) {
41
+ const response = await axios.post(`${BACKEND_URL}/ask`, { question }, { headers: this.headers, timeout: 60000 });
42
+ return response.data;
43
+ }
44
+ async addDocument(content, title, source) {
45
+ const response = await axios.post(`${BACKEND_URL}/documents`, { content, title, source }, { headers: this.headers, timeout: 30000 });
46
+ return response.data;
47
+ }
48
+ async listDocuments(limit = 20) {
49
+ const response = await axios.get(`${BACKEND_URL}/documents?limit=${limit}`, { headers: this.headers, timeout: 30000 });
50
+ return response.data;
51
+ }
52
+ async deleteDocument(id) {
53
+ const response = await axios.delete(`${BACKEND_URL}/documents/${id}`, { headers: this.headers, timeout: 30000 });
54
+ return response.data;
55
+ }
56
+ }
57
+ // ============================================================================
58
+ // MCP Server
59
+ // ============================================================================
60
+ async function startMCPServer() {
61
+ const args = parseArguments();
62
+ const backend = new BackendClient(args.accessToken);
63
+ const server = new Server({
64
+ name: 'parisinnov-mcp',
65
+ version: '1.0.0',
66
+ }, {
67
+ capabilities: { tools: {} },
68
+ });
69
+ // List available tools
70
+ server.setRequestHandler(ListToolsRequestSchema, async () => ({
71
+ tools: [
72
+ {
73
+ name: 'search-context',
74
+ description: 'Search your knowledge base and get AI-powered answers using GLM-4.7.',
75
+ inputSchema: {
76
+ type: 'object',
77
+ properties: {
78
+ question: {
79
+ type: 'string',
80
+ description: 'Your question or search query'
81
+ }
82
+ },
83
+ required: ['question']
84
+ }
85
+ },
86
+ {
87
+ name: 'add-knowledge',
88
+ description: 'Add new content to your knowledge base. It will be vectorized and available for future searches.',
89
+ inputSchema: {
90
+ type: 'object',
91
+ properties: {
92
+ content: {
93
+ type: 'string',
94
+ description: 'The content to add'
95
+ },
96
+ title: {
97
+ type: 'string',
98
+ description: 'Optional title for the content'
99
+ },
100
+ source: {
101
+ type: 'string',
102
+ description: 'Optional source identifier (e.g., "slack", "notion", "manual")'
103
+ }
104
+ },
105
+ required: ['content']
106
+ }
107
+ },
108
+ {
109
+ name: 'list-knowledge',
110
+ description: 'List documents in your knowledge base',
111
+ inputSchema: {
112
+ type: 'object',
113
+ properties: {
114
+ limit: {
115
+ type: 'number',
116
+ description: 'Maximum number of documents to return (default: 20)'
117
+ }
118
+ }
119
+ }
120
+ },
121
+ {
122
+ name: 'delete-knowledge',
123
+ description: 'Delete a document from your knowledge base',
124
+ inputSchema: {
125
+ type: 'object',
126
+ properties: {
127
+ id: {
128
+ type: 'string',
129
+ description: 'The document ID to delete'
130
+ }
131
+ },
132
+ required: ['id']
133
+ }
134
+ }
135
+ ]
136
+ }));
137
+ // Handle tool calls
138
+ server.setRequestHandler(CallToolRequestSchema, async (request) => {
139
+ const { name, arguments: toolArgs } = request.params;
140
+ try {
141
+ switch (name) {
142
+ case 'search-context': {
143
+ const { question } = toolArgs;
144
+ if (!question || typeof question !== 'string') {
145
+ throw new Error('Question is required');
146
+ }
147
+ const result = await backend.ask(question);
148
+ let responseText = result.answer;
149
+ if (result.sources.length > 0) {
150
+ responseText += '\n\n---\n**Sources:**';
151
+ result.sources.forEach((source, i) => {
152
+ responseText += `\n${i + 1}. ${source.title || 'Document'} (${(source.similarity * 100).toFixed(0)}%)`;
153
+ });
154
+ }
155
+ responseText += `\n\n_${result.metadata.documents_found} docs | ${result.metadata.processing_time_ms}ms | ${result.metadata.model}_`;
156
+ return {
157
+ content: [{ type: 'text', text: responseText }]
158
+ };
159
+ }
160
+ case 'add-knowledge': {
161
+ const { content, title, source } = toolArgs;
162
+ if (!content || typeof content !== 'string') {
163
+ throw new Error('Content is required');
164
+ }
165
+ const result = await backend.addDocument(content, title, source);
166
+ return {
167
+ content: [{
168
+ type: 'text',
169
+ text: `Document added!\nID: ${result.document.id}\nTitle: ${result.document.title}`
170
+ }]
171
+ };
172
+ }
173
+ case 'list-knowledge': {
174
+ const { limit } = toolArgs;
175
+ const result = await backend.listDocuments(limit || 20);
176
+ if (result.documents.length === 0) {
177
+ return {
178
+ content: [{ type: 'text', text: 'No documents in knowledge base.' }]
179
+ };
180
+ }
181
+ let text = `**${result.documents.length} document(s):**\n\n`;
182
+ result.documents.forEach((doc, i) => {
183
+ text += `${i + 1}. **${doc.title}** (ID: \`${doc.id}\`)\n`;
184
+ text += ` ${doc.snippet}\n\n`;
185
+ });
186
+ return {
187
+ content: [{ type: 'text', text }]
188
+ };
189
+ }
190
+ case 'delete-knowledge': {
191
+ const { id } = toolArgs;
192
+ if (!id) {
193
+ throw new Error('Document ID is required');
194
+ }
195
+ const result = await backend.deleteDocument(id);
196
+ return {
197
+ content: [{
198
+ type: 'text',
199
+ text: result.success
200
+ ? `Document ${id} deleted.`
201
+ : `Failed to delete document ${id}.`
202
+ }]
203
+ };
204
+ }
205
+ default:
206
+ throw new Error(`Unknown tool: ${name}`);
207
+ }
208
+ }
209
+ catch (error) {
210
+ const message = error instanceof Error ? error.message : 'Unknown error';
211
+ if (axios.isAxiosError(error)) {
212
+ if (error.response) {
213
+ return {
214
+ content: [{
215
+ type: 'text',
216
+ text: `Backend error (${error.response.status}): ${error.response.data?.message || error.message}`
217
+ }],
218
+ isError: true
219
+ };
220
+ }
221
+ return {
222
+ content: [{ type: 'text', text: `Network error: ${message}` }],
223
+ isError: true
224
+ };
225
+ }
226
+ return {
227
+ content: [{ type: 'text', text: `Error: ${message}` }],
228
+ isError: true
229
+ };
230
+ }
231
+ });
232
+ // Start server
233
+ const transport = new StdioServerTransport();
234
+ await server.connect(transport);
235
+ }
236
+ // Error handlers
237
+ process.on('uncaughtException', (error) => {
238
+ console.error('Uncaught exception:', error);
239
+ process.exit(1);
240
+ });
241
+ process.on('unhandledRejection', (reason) => {
242
+ console.error('Unhandled rejection:', reason);
243
+ process.exit(1);
244
+ });
245
+ // Start
246
+ startMCPServer().catch((error) => {
247
+ console.error('Failed to start MCP server:', error);
248
+ process.exit(1);
249
+ });
package/package.json ADDED
@@ -0,0 +1,42 @@
1
+ {
2
+ "name": "parisinnov-mcp",
3
+ "version": "1.0.0",
4
+ "description": "MCP Server with Smart Query Builder (GLM-4.7) for RAG-powered knowledge base",
5
+ "type": "module",
6
+ "main": "dist/index.js",
7
+ "bin": {
8
+ "parisinnov-mcp": "dist/index.js"
9
+ },
10
+ "scripts": {
11
+ "build": "tsc",
12
+ "start": "node dist/index.js",
13
+ "dev": "ts-node --esm src/index.ts",
14
+ "prepublishOnly": "npm run build"
15
+ },
16
+ "keywords": ["mcp", "model-context-protocol", "rag", "ai", "claude", "cursor", "glm", "featherless", "knowledge-base"],
17
+ "author": "Paris Innov Hackathon Team",
18
+ "license": "MIT",
19
+ "repository": {
20
+ "type": "git",
21
+ "url": "git+https://github.com/martinbon39/parisinnov-mcp.git"
22
+ },
23
+ "bugs": {
24
+ "url": "https://github.com/martinbon39/parisinnov-mcp/issues"
25
+ },
26
+ "homepage": "https://github.com/martinbon39/parisinnov-mcp#readme",
27
+ "files": ["dist/", "README.md"],
28
+ "dependencies": {
29
+ "@modelcontextprotocol/sdk": "^0.5.0",
30
+ "axios": "^1.6.0",
31
+ "yargs": "^17.7.0"
32
+ },
33
+ "devDependencies": {
34
+ "@types/node": "^20.0.0",
35
+ "@types/yargs": "^17.0.0",
36
+ "ts-node": "^10.9.0",
37
+ "typescript": "^5.0.0"
38
+ },
39
+ "engines": {
40
+ "node": ">=18.0.0"
41
+ }
42
+ }