mcp-pickaxe 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/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2024
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,221 @@
1
+ # MCP Pickaxe Server
2
+
3
+ [![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://opensource.org/licenses/MIT)
4
+ [![MCP](https://img.shields.io/badge/MCP-Compatible-blue)](https://modelcontextprotocol.io)
5
+
6
+ An MCP (Model Context Protocol) server that connects AI assistants like Claude to the [Pickaxe](https://pickaxe.co) platform. Manage your AI agents, knowledge bases, users, and analytics directly through natural language.
7
+
8
+ ## Why Use This?
9
+
10
+ If you're building AI agents on Pickaxe, this MCP server lets you:
11
+
12
+ - **Analyze agent conversations** - Review chat history to identify knowledge gaps and improve agent performance
13
+ - **Manage knowledge bases** - Create, update, and connect documents to your agents without leaving your AI workflow
14
+ - **Handle user management** - Create users, manage access, send invitations, and track usage
15
+ - **Work across multiple studios** - Seamlessly switch between different Pickaxe studios in a single session
16
+ - **Automate workflows** - Let Claude handle repetitive Pickaxe admin tasks
17
+
18
+ ## Features
19
+
20
+ | Category | Tools |
21
+ |----------|-------|
22
+ | **Studios** | List configured studios, switch between them |
23
+ | **Chat History** | Fetch and analyze agent conversation logs |
24
+ | **Documents** | Create, list, get, delete, connect/disconnect to agents |
25
+ | **Users** | Create, list, get, update, delete, invite |
26
+ | **Products** | List available products and bundles |
27
+ | **Memory** | List memory schemas, retrieve user memories |
28
+
29
+ ## Prerequisites
30
+
31
+ - Node.js 18+
32
+ - A [Pickaxe](https://pickaxe.co) account with API access
33
+ - Your Pickaxe Studio API key(s)
34
+
35
+ ## Installation
36
+
37
+ ### Option 1: Clone and Build
38
+
39
+ ```bash
40
+ git clone https://github.com/YOUR_USERNAME/mcp-pickaxe.git
41
+ cd mcp-pickaxe
42
+ npm install
43
+ npm run build
44
+ ```
45
+
46
+ ### Option 2: Install from npm (coming soon)
47
+
48
+ ```bash
49
+ npm install -g mcp-pickaxe
50
+ ```
51
+
52
+ ## Configuration
53
+
54
+ ### 1. Get Your Pickaxe API Key
55
+
56
+ 1. Log in to [Pickaxe Studio](https://studio.pickaxe.co)
57
+ 2. Navigate to Settings > API
58
+ 3. Copy your Studio API key (starts with `studio-`)
59
+
60
+ ### 2. Configure Your MCP Client
61
+
62
+ #### For Claude Desktop
63
+
64
+ Add to your Claude Desktop config file:
65
+
66
+ **macOS**: `~/Library/Application Support/Claude/claude_desktop_config.json`
67
+ **Windows**: `%APPDATA%\Claude\claude_desktop_config.json`
68
+
69
+ ```json
70
+ {
71
+ "mcpServers": {
72
+ "pickaxe": {
73
+ "command": "node",
74
+ "args": ["/path/to/mcp-pickaxe/dist/index.js"],
75
+ "env": {
76
+ "PICKAXE_STUDIO_MAIN": "studio-your-api-key-here"
77
+ }
78
+ }
79
+ }
80
+ }
81
+ ```
82
+
83
+ #### For Claude Code
84
+
85
+ Add to `~/.claude.json`:
86
+
87
+ ```json
88
+ {
89
+ "mcpServers": {
90
+ "pickaxe": {
91
+ "command": "node",
92
+ "args": ["/path/to/mcp-pickaxe/dist/index.js"],
93
+ "env": {
94
+ "PICKAXE_STUDIO_MAIN": "studio-your-api-key-here"
95
+ }
96
+ }
97
+ }
98
+ }
99
+ ```
100
+
101
+ ### Multi-Studio Configuration
102
+
103
+ To work with multiple Pickaxe studios, add multiple environment variables:
104
+
105
+ ```json
106
+ {
107
+ "env": {
108
+ "PICKAXE_STUDIO_PRODUCTION": "studio-xxx-xxx-xxx",
109
+ "PICKAXE_STUDIO_STAGING": "studio-yyy-yyy-yyy",
110
+ "PICKAXE_STUDIO_DEV": "studio-zzz-zzz-zzz",
111
+ "PICKAXE_DEFAULT_STUDIO": "PRODUCTION"
112
+ }
113
+ }
114
+ ```
115
+
116
+ Then specify which studio to use in your requests:
117
+ - If you set `PICKAXE_DEFAULT_STUDIO`, that studio is used when none is specified
118
+ - If only one studio is configured, it's used automatically
119
+ - Otherwise, pass `studio="STAGING"` (or similar) to any tool
120
+
121
+ ## Usage Examples
122
+
123
+ Once configured, you can interact with Pickaxe through natural language:
124
+
125
+ ### Analyze Agent Performance
126
+ > "Show me the last 20 conversations from my support agent"
127
+
128
+ > "What questions are users asking that my agent can't answer?"
129
+
130
+ ### Manage Knowledge Base
131
+ > "Create a new document called 'FAQ' with this content: [your content]"
132
+
133
+ > "Connect the FAQ document to my customer support agent"
134
+
135
+ > "List all documents in my knowledge base"
136
+
137
+ ### User Management
138
+ > "Show me all users and their usage stats"
139
+
140
+ > "Create a new user with email user@example.com and give them access to the Pro product"
141
+
142
+ > "Send invitations to these emails: [list of emails]"
143
+
144
+ ### Multi-Studio Operations
145
+ > "List all users in my staging studio"
146
+
147
+ > "Compare the documents between production and staging"
148
+
149
+ ## Available Tools
150
+
151
+ ### Studio Management
152
+ - `studios_list` - List all configured studios and the current default
153
+
154
+ ### Chat History
155
+ - `chat_history` - Fetch conversation history for an agent
156
+ - Parameters: `pickaxeId`, `skip`, `limit`, `format` ("messages" or "raw"), `studio`
157
+
158
+ ### Document Management
159
+ - `doc_create` - Create document from content or URL
160
+ - `doc_list` - List all documents (with pagination)
161
+ - `doc_get` - Get a specific document
162
+ - `doc_delete` - Delete a document
163
+ - `doc_connect` - Link document to an agent
164
+ - `doc_disconnect` - Unlink document from an agent
165
+
166
+ ### User Management
167
+ - `user_list` - List all users with access and usage info
168
+ - `user_get` - Get a specific user by email
169
+ - `user_create` - Create a new user
170
+ - `user_update` - Update user details, products, or usage
171
+ - `user_delete` - Delete a user
172
+ - `user_invite` - Send email invitations
173
+
174
+ ### Products
175
+ - `products_list` - List available products/bundles
176
+
177
+ ### Memory
178
+ - `memory_list` - List memory schemas
179
+ - `memory_get_user` - Get collected memories for a user
180
+
181
+ ## Development
182
+
183
+ ```bash
184
+ # Run in development mode (auto-reloads)
185
+ npm run dev
186
+
187
+ # Build for production
188
+ npm run build
189
+
190
+ # Run the built version
191
+ npm start
192
+ ```
193
+
194
+ ## Troubleshooting
195
+
196
+ ### "No Pickaxe studios configured"
197
+ Ensure you have at least one `PICKAXE_STUDIO_*` environment variable set in your MCP config.
198
+
199
+ ### "Studio not found"
200
+ Check that the studio name matches exactly (case-insensitive). Run `studios_list` to see available options.
201
+
202
+ ### "Pickaxe API error (401)"
203
+ Your API key is invalid or expired. Get a new one from Pickaxe Studio settings.
204
+
205
+ ### "Pickaxe API error (403)"
206
+ Your API key doesn't have permission for this operation. Check your Pickaxe account permissions.
207
+
208
+ ## Contributing
209
+
210
+ Contributions are welcome! Please see [CONTRIBUTING.md](CONTRIBUTING.md) for guidelines.
211
+
212
+ ## License
213
+
214
+ MIT License - see [LICENSE](LICENSE) for details.
215
+
216
+ ## Links
217
+
218
+ - [Pickaxe Platform](https://pickaxe.co)
219
+ - [Pickaxe Studio](https://studio.pickaxe.co)
220
+ - [Model Context Protocol](https://modelcontextprotocol.io)
221
+ - [MCP Specification](https://spec.modelcontextprotocol.io)
@@ -0,0 +1,2 @@
1
+ #!/usr/bin/env node
2
+ export {};
package/dist/index.js ADDED
@@ -0,0 +1,594 @@
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
+ // Pickaxe API configuration
6
+ const PICKAXE_BASE_URL = "https://api.pickaxe.co/v1";
7
+ const DEFAULT_STUDIO = process.env.PICKAXE_DEFAULT_STUDIO;
8
+ // Get all configured studios from environment
9
+ function getConfiguredStudios() {
10
+ const studios = [];
11
+ for (const key of Object.keys(process.env)) {
12
+ if (key.startsWith("PICKAXE_STUDIO_")) {
13
+ const studioName = key.replace("PICKAXE_STUDIO_", "");
14
+ studios.push(studioName);
15
+ }
16
+ }
17
+ return studios;
18
+ }
19
+ // Get API key for a studio
20
+ function getApiKey(studio) {
21
+ const studioName = studio ?? DEFAULT_STUDIO;
22
+ if (!studioName) {
23
+ const studios = getConfiguredStudios();
24
+ if (studios.length === 1) {
25
+ // Only one studio configured, use it
26
+ return process.env[`PICKAXE_STUDIO_${studios[0]}`];
27
+ }
28
+ throw new Error(`No studio specified and no default set. Available studios: ${studios.join(", ")}. ` +
29
+ `Set PICKAXE_DEFAULT_STUDIO or pass 'studio' parameter.`);
30
+ }
31
+ const apiKey = process.env[`PICKAXE_STUDIO_${studioName.toUpperCase()}`];
32
+ if (!apiKey) {
33
+ const studios = getConfiguredStudios();
34
+ throw new Error(`Studio "${studioName}" not found. Available studios: ${studios.join(", ")}. ` +
35
+ `Configure with PICKAXE_STUDIO_${studioName.toUpperCase()} environment variable.`);
36
+ }
37
+ return apiKey;
38
+ }
39
+ // Validate at least one studio is configured
40
+ const configuredStudios = getConfiguredStudios();
41
+ if (configuredStudios.length === 0) {
42
+ console.error("Error: No Pickaxe studios configured.");
43
+ console.error("Set environment variables like PICKAXE_STUDIO_RRHUB=your-api-key");
44
+ process.exit(1);
45
+ }
46
+ console.error(`Pickaxe MCP server initialized with studios: ${configuredStudios.join(", ")}`);
47
+ if (DEFAULT_STUDIO) {
48
+ console.error(`Default studio: ${DEFAULT_STUDIO}`);
49
+ }
50
+ // API helper function
51
+ async function pickaxeRequest(endpoint, method = "GET", body, studio) {
52
+ const apiKey = getApiKey(studio);
53
+ const url = endpoint.startsWith("http") ? endpoint : `${PICKAXE_BASE_URL}${endpoint}`;
54
+ const options = {
55
+ method,
56
+ headers: {
57
+ "Content-Type": "application/json",
58
+ "Authorization": `Bearer ${apiKey}`,
59
+ },
60
+ };
61
+ if (body && method !== "GET") {
62
+ options.body = JSON.stringify(body);
63
+ }
64
+ const response = await fetch(url, options);
65
+ if (!response.ok) {
66
+ const errorText = await response.text();
67
+ throw new Error(`Pickaxe API error (${response.status}): ${errorText}`);
68
+ }
69
+ return response.json();
70
+ }
71
+ // Studio parameter schema (added to all tools)
72
+ const studioParam = {
73
+ type: "string",
74
+ description: `Studio name to use. Available: ${configuredStudios.join(", ")}. Default: ${DEFAULT_STUDIO || configuredStudios[0]}`,
75
+ };
76
+ // Define all tools
77
+ const tools = [
78
+ // Studio management
79
+ {
80
+ name: "studios_list",
81
+ description: "List all configured Pickaxe studios and the current default.",
82
+ inputSchema: {
83
+ type: "object",
84
+ properties: {},
85
+ },
86
+ },
87
+ // Chat History
88
+ {
89
+ name: "chat_history",
90
+ description: "Fetch conversation history for a Pickaxe agent. Use to analyze user questions, identify KB gaps, and review agent performance.",
91
+ inputSchema: {
92
+ type: "object",
93
+ properties: {
94
+ studio: studioParam,
95
+ pickaxeId: {
96
+ type: "string",
97
+ description: "The Pickaxe agent ID (from the agent URL or config)",
98
+ },
99
+ skip: {
100
+ type: "number",
101
+ description: "Number of conversations to skip (for pagination). Default: 0",
102
+ },
103
+ limit: {
104
+ type: "number",
105
+ description: "Maximum conversations to return. Default: 10, Max: 100",
106
+ },
107
+ format: {
108
+ type: "string",
109
+ enum: ["messages", "raw"],
110
+ description: "Output format. 'messages' is human-readable, 'raw' includes metadata. Default: messages",
111
+ },
112
+ },
113
+ required: ["pickaxeId"],
114
+ },
115
+ },
116
+ // Document tools
117
+ {
118
+ name: "doc_create",
119
+ description: "Create a new document in Pickaxe knowledge base. Can create from raw content or scrape a website URL.",
120
+ inputSchema: {
121
+ type: "object",
122
+ properties: {
123
+ studio: studioParam,
124
+ name: {
125
+ type: "string",
126
+ description: "Name/title of the document",
127
+ },
128
+ rawContent: {
129
+ type: "string",
130
+ description: "Raw text content for the document. Use this OR website, not both.",
131
+ },
132
+ website: {
133
+ type: "string",
134
+ description: "URL to scrape as document content. Use this OR rawContent, not both.",
135
+ },
136
+ },
137
+ required: ["name"],
138
+ },
139
+ },
140
+ {
141
+ name: "doc_connect",
142
+ description: "Connect/link a document to a Pickaxe agent, adding it to the agent's knowledge base.",
143
+ inputSchema: {
144
+ type: "object",
145
+ properties: {
146
+ studio: studioParam,
147
+ documentId: {
148
+ type: "string",
149
+ description: "The document ID to connect",
150
+ },
151
+ pickaxeId: {
152
+ type: "string",
153
+ description: "The Pickaxe agent ID to connect the document to",
154
+ },
155
+ },
156
+ required: ["documentId", "pickaxeId"],
157
+ },
158
+ },
159
+ {
160
+ name: "doc_disconnect",
161
+ description: "Disconnect/unlink a document from a Pickaxe agent, removing it from the agent's knowledge base.",
162
+ inputSchema: {
163
+ type: "object",
164
+ properties: {
165
+ studio: studioParam,
166
+ documentId: {
167
+ type: "string",
168
+ description: "The document ID to disconnect",
169
+ },
170
+ pickaxeId: {
171
+ type: "string",
172
+ description: "The Pickaxe agent ID to disconnect the document from",
173
+ },
174
+ },
175
+ required: ["documentId", "pickaxeId"],
176
+ },
177
+ },
178
+ {
179
+ name: "doc_list",
180
+ description: "List all documents in the Pickaxe studio with pagination.",
181
+ inputSchema: {
182
+ type: "object",
183
+ properties: {
184
+ studio: studioParam,
185
+ skip: {
186
+ type: "number",
187
+ description: "Number of documents to skip. Default: 0",
188
+ },
189
+ take: {
190
+ type: "number",
191
+ description: "Number of documents to return. Default: 10",
192
+ },
193
+ },
194
+ },
195
+ },
196
+ {
197
+ name: "doc_get",
198
+ description: "Retrieve a specific document by ID.",
199
+ inputSchema: {
200
+ type: "object",
201
+ properties: {
202
+ studio: studioParam,
203
+ documentId: {
204
+ type: "string",
205
+ description: "The document ID to retrieve",
206
+ },
207
+ },
208
+ required: ["documentId"],
209
+ },
210
+ },
211
+ {
212
+ name: "doc_delete",
213
+ description: "Delete a document from Pickaxe. This removes it from all connected agents.",
214
+ inputSchema: {
215
+ type: "object",
216
+ properties: {
217
+ studio: studioParam,
218
+ documentId: {
219
+ type: "string",
220
+ description: "The document ID to delete",
221
+ },
222
+ },
223
+ required: ["documentId"],
224
+ },
225
+ },
226
+ // User tools
227
+ {
228
+ name: "user_list",
229
+ description: "List all users in the Pickaxe studio with their product access and usage stats.",
230
+ inputSchema: {
231
+ type: "object",
232
+ properties: {
233
+ studio: studioParam,
234
+ skip: {
235
+ type: "number",
236
+ description: "Number of users to skip. Default: 0",
237
+ },
238
+ take: {
239
+ type: "number",
240
+ description: "Number of users to return. Default: 10",
241
+ },
242
+ },
243
+ },
244
+ },
245
+ {
246
+ name: "user_get",
247
+ description: "Get details for a specific user by email.",
248
+ inputSchema: {
249
+ type: "object",
250
+ properties: {
251
+ studio: studioParam,
252
+ email: {
253
+ type: "string",
254
+ description: "The user's email address",
255
+ },
256
+ },
257
+ required: ["email"],
258
+ },
259
+ },
260
+ {
261
+ name: "user_create",
262
+ description: "Create a new user with optional product access.",
263
+ inputSchema: {
264
+ type: "object",
265
+ properties: {
266
+ studio: studioParam,
267
+ email: {
268
+ type: "string",
269
+ description: "User's email address (required)",
270
+ },
271
+ name: {
272
+ type: "string",
273
+ description: "User's display name",
274
+ },
275
+ password: {
276
+ type: "string",
277
+ description: "User's password (optional - they can reset)",
278
+ },
279
+ products: {
280
+ type: "array",
281
+ items: { type: "string" },
282
+ description: "Array of product IDs to grant access to",
283
+ },
284
+ isEmailVerified: {
285
+ type: "boolean",
286
+ description: "Mark email as verified. Default: false",
287
+ },
288
+ },
289
+ required: ["email"],
290
+ },
291
+ },
292
+ {
293
+ name: "user_update",
294
+ description: "Update an existing user's details, products, or usage.",
295
+ inputSchema: {
296
+ type: "object",
297
+ properties: {
298
+ studio: studioParam,
299
+ email: {
300
+ type: "string",
301
+ description: "The user's email address",
302
+ },
303
+ name: {
304
+ type: "string",
305
+ description: "Updated display name",
306
+ },
307
+ products: {
308
+ type: "array",
309
+ items: { type: "string" },
310
+ description: "Updated array of product IDs",
311
+ },
312
+ currentUses: {
313
+ type: "number",
314
+ description: "Set current usage count",
315
+ },
316
+ extraUses: {
317
+ type: "number",
318
+ description: "Add extra usage allowance",
319
+ },
320
+ isEmailVerified: {
321
+ type: "boolean",
322
+ description: "Update email verification status",
323
+ },
324
+ },
325
+ required: ["email"],
326
+ },
327
+ },
328
+ {
329
+ name: "user_delete",
330
+ description: "Delete a user by email.",
331
+ inputSchema: {
332
+ type: "object",
333
+ properties: {
334
+ studio: studioParam,
335
+ email: {
336
+ type: "string",
337
+ description: "The user's email address to delete",
338
+ },
339
+ },
340
+ required: ["email"],
341
+ },
342
+ },
343
+ {
344
+ name: "user_invite",
345
+ description: "Send email invitations to new users with optional product access.",
346
+ inputSchema: {
347
+ type: "object",
348
+ properties: {
349
+ studio: studioParam,
350
+ emails: {
351
+ type: "array",
352
+ items: { type: "string" },
353
+ description: "Array of email addresses to invite",
354
+ },
355
+ productIds: {
356
+ type: "array",
357
+ items: { type: "string" },
358
+ description: "Array of product IDs to grant access to",
359
+ },
360
+ },
361
+ required: ["emails"],
362
+ },
363
+ },
364
+ // Product tools
365
+ {
366
+ name: "products_list",
367
+ description: "List all available products/bundles in the Pickaxe studio.",
368
+ inputSchema: {
369
+ type: "object",
370
+ properties: {
371
+ studio: studioParam,
372
+ },
373
+ },
374
+ },
375
+ // Memory tools
376
+ {
377
+ name: "memory_list",
378
+ description: "List all memory schemas defined in the studio.",
379
+ inputSchema: {
380
+ type: "object",
381
+ properties: {
382
+ studio: studioParam,
383
+ skip: {
384
+ type: "number",
385
+ description: "Number of memories to skip. Default: 0",
386
+ },
387
+ take: {
388
+ type: "number",
389
+ description: "Number of memories to return. Default: 10",
390
+ },
391
+ },
392
+ },
393
+ },
394
+ {
395
+ name: "memory_get_user",
396
+ description: "Get all collected memories for a specific user.",
397
+ inputSchema: {
398
+ type: "object",
399
+ properties: {
400
+ studio: studioParam,
401
+ email: {
402
+ type: "string",
403
+ description: "The user's email address",
404
+ },
405
+ memoryId: {
406
+ type: "string",
407
+ description: "Optional: specific memory schema ID to filter by",
408
+ },
409
+ skip: {
410
+ type: "number",
411
+ description: "Number of memories to skip. Default: 0",
412
+ },
413
+ take: {
414
+ type: "number",
415
+ description: "Number of memories to return. Default: 10",
416
+ },
417
+ },
418
+ required: ["email"],
419
+ },
420
+ },
421
+ ];
422
+ // Tool execution handlers
423
+ async function executeTool(name, args) {
424
+ const studio = args.studio;
425
+ switch (name) {
426
+ // Studio management
427
+ case "studios_list": {
428
+ const studios = getConfiguredStudios();
429
+ const result = {
430
+ studios,
431
+ default: DEFAULT_STUDIO || (studios.length === 1 ? studios[0] : null),
432
+ count: studios.length,
433
+ };
434
+ return JSON.stringify(result, null, 2);
435
+ }
436
+ // Chat History
437
+ case "chat_history": {
438
+ const result = await pickaxeRequest("/studio/pickaxe/history", "POST", {
439
+ pickaxeId: args.pickaxeId,
440
+ skip: args.skip ?? 0,
441
+ limit: args.limit ?? 10,
442
+ format: args.format ?? "messages",
443
+ }, studio);
444
+ return JSON.stringify(result, null, 2);
445
+ }
446
+ // Document tools
447
+ case "doc_create": {
448
+ const body = { name: args.name };
449
+ if (args.rawContent)
450
+ body.rawContent = args.rawContent;
451
+ if (args.website)
452
+ body.website = args.website;
453
+ const result = await pickaxeRequest("/studio/document/create", "POST", body, studio);
454
+ return JSON.stringify(result, null, 2);
455
+ }
456
+ case "doc_connect": {
457
+ const result = await pickaxeRequest("/studio/document/connect", "POST", {
458
+ documentId: args.documentId,
459
+ pickaxeId: args.pickaxeId,
460
+ }, studio);
461
+ return JSON.stringify(result, null, 2);
462
+ }
463
+ case "doc_disconnect": {
464
+ const result = await pickaxeRequest("/studio/document/disconnect", "POST", {
465
+ documentId: args.documentId,
466
+ pickaxeId: args.pickaxeId,
467
+ }, studio);
468
+ return JSON.stringify(result, null, 2);
469
+ }
470
+ case "doc_list": {
471
+ const skip = args.skip ?? 0;
472
+ const take = args.take ?? 10;
473
+ const result = await pickaxeRequest(`/studio/document/list?skip=${skip}&take=${take}`, "GET", undefined, studio);
474
+ return JSON.stringify(result, null, 2);
475
+ }
476
+ case "doc_get": {
477
+ const result = await pickaxeRequest(`/studio/document/${args.documentId}`, "GET", undefined, studio);
478
+ return JSON.stringify(result, null, 2);
479
+ }
480
+ case "doc_delete": {
481
+ const result = await pickaxeRequest(`/studio/document/${args.documentId}`, "DELETE", undefined, studio);
482
+ return JSON.stringify(result, null, 2);
483
+ }
484
+ // User tools
485
+ case "user_list": {
486
+ const skip = args.skip ?? 0;
487
+ const take = args.take ?? 10;
488
+ const result = await pickaxeRequest(`/studio/user/list?skip=${skip}&take=${take}`, "GET", undefined, studio);
489
+ return JSON.stringify(result, null, 2);
490
+ }
491
+ case "user_get": {
492
+ const result = await pickaxeRequest(`/studio/user/${encodeURIComponent(args.email)}`, "GET", undefined, studio);
493
+ return JSON.stringify(result, null, 2);
494
+ }
495
+ case "user_create": {
496
+ const result = await pickaxeRequest("/studio/user/create", "POST", {
497
+ email: args.email,
498
+ name: args.name,
499
+ password: args.password,
500
+ products: args.products,
501
+ isEmailVerified: args.isEmailVerified ?? false,
502
+ }, studio);
503
+ return JSON.stringify(result, null, 2);
504
+ }
505
+ case "user_update": {
506
+ const data = {};
507
+ if (args.name !== undefined)
508
+ data.name = args.name;
509
+ if (args.products !== undefined)
510
+ data.products = args.products;
511
+ if (args.currentUses !== undefined)
512
+ data.currentUses = args.currentUses;
513
+ if (args.extraUses !== undefined)
514
+ data.extraUses = args.extraUses;
515
+ if (args.isEmailVerified !== undefined)
516
+ data.isEmailVerified = args.isEmailVerified;
517
+ const result = await pickaxeRequest(`/studio/user/${encodeURIComponent(args.email)}`, "PATCH", { data }, studio);
518
+ return JSON.stringify(result, null, 2);
519
+ }
520
+ case "user_delete": {
521
+ const result = await pickaxeRequest(`/studio/user/${encodeURIComponent(args.email)}`, "DELETE", undefined, studio);
522
+ return JSON.stringify(result, null, 2);
523
+ }
524
+ case "user_invite": {
525
+ const result = await pickaxeRequest("/studio/user/invite", "POST", {
526
+ emails: args.emails,
527
+ productIds: args.productIds,
528
+ }, studio);
529
+ return JSON.stringify(result, null, 2);
530
+ }
531
+ // Product tools
532
+ case "products_list": {
533
+ const result = await pickaxeRequest("/studio/product/list", "GET", undefined, studio);
534
+ return JSON.stringify(result, null, 2);
535
+ }
536
+ // Memory tools
537
+ case "memory_list": {
538
+ const skip = args.skip ?? 0;
539
+ const take = args.take ?? 10;
540
+ const result = await pickaxeRequest(`/studio/memory/list?skip=${skip}&take=${take}`, "GET", undefined, studio);
541
+ return JSON.stringify(result, null, 2);
542
+ }
543
+ case "memory_get_user": {
544
+ let url = `/studio/memory/user/${encodeURIComponent(args.email)}?`;
545
+ if (args.memoryId)
546
+ url += `memoryId=${args.memoryId}&`;
547
+ url += `skip=${args.skip ?? 0}&take=${args.take ?? 10}`;
548
+ const result = await pickaxeRequest(url, "GET", undefined, studio);
549
+ return JSON.stringify(result, null, 2);
550
+ }
551
+ default:
552
+ throw new Error(`Unknown tool: ${name}`);
553
+ }
554
+ }
555
+ // Create and run the server
556
+ const server = new Server({
557
+ name: "mcp-pickaxe",
558
+ version: "1.1.0",
559
+ }, {
560
+ capabilities: {
561
+ tools: {},
562
+ },
563
+ });
564
+ // Register tool list handler
565
+ server.setRequestHandler(ListToolsRequestSchema, async () => {
566
+ return { tools };
567
+ });
568
+ // Register tool execution handler
569
+ server.setRequestHandler(CallToolRequestSchema, async (request) => {
570
+ const { name, arguments: args } = request.params;
571
+ try {
572
+ const result = await executeTool(name, args ?? {});
573
+ return {
574
+ content: [{ type: "text", text: result }],
575
+ };
576
+ }
577
+ catch (error) {
578
+ const errorMessage = error instanceof Error ? error.message : String(error);
579
+ return {
580
+ content: [{ type: "text", text: `Error: ${errorMessage}` }],
581
+ isError: true,
582
+ };
583
+ }
584
+ });
585
+ // Start the server
586
+ async function main() {
587
+ const transport = new StdioServerTransport();
588
+ await server.connect(transport);
589
+ console.error("Pickaxe MCP server running on stdio");
590
+ }
591
+ main().catch((error) => {
592
+ console.error("Fatal error:", error);
593
+ process.exit(1);
594
+ });
package/package.json ADDED
@@ -0,0 +1,50 @@
1
+ {
2
+ "name": "mcp-pickaxe",
3
+ "version": "1.0.0",
4
+ "description": "MCP server for Pickaxe API - manage AI agents, knowledge bases, users, and analytics",
5
+ "type": "module",
6
+ "main": "dist/index.js",
7
+ "bin": {
8
+ "mcp-pickaxe": "dist/index.js"
9
+ },
10
+ "scripts": {
11
+ "build": "tsc",
12
+ "start": "node dist/index.js",
13
+ "dev": "tsx src/index.ts"
14
+ },
15
+ "keywords": [
16
+ "mcp",
17
+ "model-context-protocol",
18
+ "pickaxe",
19
+ "ai-agents",
20
+ "claude",
21
+ "anthropic",
22
+ "knowledge-base"
23
+ ],
24
+ "author": "",
25
+ "license": "MIT",
26
+ "repository": {
27
+ "type": "git",
28
+ "url": "https://github.com/aplaceforallmystuff/mcp-pickaxe.git"
29
+ },
30
+ "bugs": {
31
+ "url": "https://github.com/aplaceforallmystuff/mcp-pickaxe/issues"
32
+ },
33
+ "homepage": "https://github.com/aplaceforallmystuff/mcp-pickaxe#readme",
34
+ "engines": {
35
+ "node": ">=18.0.0"
36
+ },
37
+ "files": [
38
+ "dist",
39
+ "README.md",
40
+ "LICENSE"
41
+ ],
42
+ "dependencies": {
43
+ "@modelcontextprotocol/sdk": "^1.0.0"
44
+ },
45
+ "devDependencies": {
46
+ "@types/node": "^20.10.0",
47
+ "tsx": "^4.7.0",
48
+ "typescript": "^5.3.0"
49
+ }
50
+ }