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 +21 -0
- package/README.md +221 -0
- package/dist/index.d.ts +2 -0
- package/dist/index.js +594 -0
- package/package.json +50 -0
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
|
+
[](https://opensource.org/licenses/MIT)
|
|
4
|
+
[](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)
|
package/dist/index.d.ts
ADDED
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
|
+
}
|