pulsemcp-cms-admin-mcp-server 0.4.4 → 0.5.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 +105 -30
- package/build/shared/src/tools.js +76 -46
- package/package.json +1 -1
- package/shared/tools.d.ts +19 -15
- package/shared/tools.js +76 -46
package/README.md
CHANGED
|
@@ -32,7 +32,7 @@ This is an MCP ([Model Context Protocol](https://modelcontextprotocol.io/)) Serv
|
|
|
32
32
|
|
|
33
33
|
**MCP Implementation Search**: Search for MCP servers and clients in the PulseMCP registry.
|
|
34
34
|
|
|
35
|
-
**
|
|
35
|
+
**Tool Groups**: Enable/disable tool groups via `TOOL_GROUPS` environment variable. Each group has a base variant (full access) and a `_readonly` variant (read-only access).
|
|
36
36
|
|
|
37
37
|
**Draft Control**: Manage draft posts before publishing to the newsletter.
|
|
38
38
|
|
|
@@ -40,38 +40,95 @@ This is an MCP ([Model Context Protocol](https://modelcontextprotocol.io/)) Serv
|
|
|
40
40
|
|
|
41
41
|
This server is built and tested on macOS with Claude Desktop. It should work with other MCP clients as well.
|
|
42
42
|
|
|
43
|
-
| Tool Name | Tool Group
|
|
44
|
-
| -------------------------------------- |
|
|
45
|
-
| `get_newsletter_posts` | newsletter
|
|
46
|
-
| `get_newsletter_post` | newsletter
|
|
47
|
-
| `draft_newsletter_post` | newsletter
|
|
48
|
-
| `update_newsletter_post` | newsletter
|
|
49
|
-
| `upload_image` | newsletter
|
|
50
|
-
| `get_authors` | newsletter
|
|
51
|
-
| `search_mcp_implementations` |
|
|
52
|
-
| `get_draft_mcp_implementations` |
|
|
53
|
-
| `find_providers` |
|
|
54
|
-
| `save_mcp_implementation` |
|
|
55
|
-
| `send_impl_posted_notif` |
|
|
56
|
-
| `get_official_mirror_queue_items` |
|
|
57
|
-
| `get_official_mirror_queue_item` |
|
|
58
|
-
| `approve_official_mirror_queue_item` |
|
|
59
|
-
| `approve_mirror_no_modify` |
|
|
60
|
-
| `reject_official_mirror_queue_item` |
|
|
61
|
-
| `add_official_mirror_to_regular_queue` |
|
|
62
|
-
| `unlink_official_mirror_queue_item` |
|
|
43
|
+
| Tool Name | Tool Group | Read/Write | Description |
|
|
44
|
+
| -------------------------------------- | -------------- | ---------- | ---------------------------------------------------------------------------- |
|
|
45
|
+
| `get_newsletter_posts` | newsletter | read | List newsletter posts with search, sorting, and pagination options. |
|
|
46
|
+
| `get_newsletter_post` | newsletter | read | Retrieve a specific newsletter post by its unique slug. |
|
|
47
|
+
| `draft_newsletter_post` | newsletter | write | Create a new draft newsletter post with title, body, and metadata. |
|
|
48
|
+
| `update_newsletter_post` | newsletter | write | Update an existing newsletter post's content and metadata (except status). |
|
|
49
|
+
| `upload_image` | newsletter | write | Upload an image and attach it to a specific newsletter post. |
|
|
50
|
+
| `get_authors` | newsletter | read | Get a list of authors with optional search and pagination. |
|
|
51
|
+
| `search_mcp_implementations` | server_queue | read | Search for MCP servers and clients in the PulseMCP registry. |
|
|
52
|
+
| `get_draft_mcp_implementations` | server_queue | read | Retrieve paginated list of draft MCP implementations needing review. |
|
|
53
|
+
| `find_providers` | server_queue | read | Search for providers by ID, name, URL, or slug. |
|
|
54
|
+
| `save_mcp_implementation` | server_queue | write | Update an MCP implementation (replicates Admin panel "Save Changes" button). |
|
|
55
|
+
| `send_impl_posted_notif` | server_queue | write | Send email notification when MCP implementation goes live. |
|
|
56
|
+
| `get_official_mirror_queue_items` | official_queue | read | List and filter official mirror queue entries with pagination and search. |
|
|
57
|
+
| `get_official_mirror_queue_item` | official_queue | read | Get detailed information about a single official mirror queue entry. |
|
|
58
|
+
| `approve_official_mirror_queue_item` | official_queue | write | Approve a queue entry and link it to an existing MCP server (async). |
|
|
59
|
+
| `approve_mirror_no_modify` | official_queue | write | Approve without updating the linked server. |
|
|
60
|
+
| `reject_official_mirror_queue_item` | official_queue | write | Reject a queue entry (async operation). |
|
|
61
|
+
| `add_official_mirror_to_regular_queue` | official_queue | write | Convert a queue entry to a draft MCP implementation (async). |
|
|
62
|
+
| `unlink_official_mirror_queue_item` | official_queue | write | Unlink a queue entry from its linked MCP server. |
|
|
63
63
|
|
|
64
64
|
# Tool Groups
|
|
65
65
|
|
|
66
|
-
This server organizes tools into groups that can be selectively enabled or disabled:
|
|
66
|
+
This server organizes tools into groups that can be selectively enabled or disabled. Each group has two variants:
|
|
67
67
|
|
|
68
|
-
- **
|
|
69
|
-
- **
|
|
70
|
-
- **server_queue_all** (5 tools): All MCP implementation tools including write operations (search, draft retrieval, provider lookup, update, and email notification)
|
|
71
|
-
- **official_queue_readonly** (2 tools): Read-only official mirror queue tools (list, get details)
|
|
72
|
-
- **official_queue_all** (7 tools): All official mirror queue tools including approve, reject, unlink, and add to regular queue
|
|
68
|
+
- **Base group** (e.g., `newsletter`): Full read + write access
|
|
69
|
+
- **Readonly group** (e.g., `newsletter_readonly`): Read-only access
|
|
73
70
|
|
|
74
|
-
|
|
71
|
+
## Available Groups
|
|
72
|
+
|
|
73
|
+
| Group | Tools | Description |
|
|
74
|
+
| ------------------------- | ----- | -------------------------------------------- |
|
|
75
|
+
| `newsletter` | 6 | Full newsletter management (read + write) |
|
|
76
|
+
| `newsletter_readonly` | 3 | Newsletter read-only (get posts, authors) |
|
|
77
|
+
| `server_queue` | 5 | Full MCP implementation queue (read + write) |
|
|
78
|
+
| `server_queue_readonly` | 3 | MCP implementation queue read-only |
|
|
79
|
+
| `official_queue` | 7 | Full official mirror queue (read + write) |
|
|
80
|
+
| `official_queue_readonly` | 2 | Official mirror queue read-only |
|
|
81
|
+
|
|
82
|
+
### Tools by Group
|
|
83
|
+
|
|
84
|
+
- **newsletter** / **newsletter_readonly**:
|
|
85
|
+
- Read-only: `get_newsletter_posts`, `get_newsletter_post`, `get_authors`
|
|
86
|
+
- Write: `draft_newsletter_post`, `update_newsletter_post`, `upload_image`
|
|
87
|
+
- **server_queue** / **server_queue_readonly**:
|
|
88
|
+
- Read-only: `search_mcp_implementations`, `get_draft_mcp_implementations`, `find_providers`
|
|
89
|
+
- Write: `save_mcp_implementation`, `send_impl_posted_notif`
|
|
90
|
+
- **official_queue** / **official_queue_readonly**:
|
|
91
|
+
- Read-only: `get_official_mirror_queue_items`, `get_official_mirror_queue_item`
|
|
92
|
+
- Write: `approve_official_mirror_queue_item`, `approve_mirror_no_modify`, `reject_official_mirror_queue_item`, `add_official_mirror_to_regular_queue`, `unlink_official_mirror_queue_item`
|
|
93
|
+
|
|
94
|
+
## Environment Variables
|
|
95
|
+
|
|
96
|
+
| Variable | Description | Default |
|
|
97
|
+
| ------------- | ------------------------------------------- | ---------------------------------------------------------- |
|
|
98
|
+
| `TOOL_GROUPS` | Comma-separated list of enabled tool groups | `newsletter,server_queue,official_queue` (all base groups) |
|
|
99
|
+
|
|
100
|
+
## Examples
|
|
101
|
+
|
|
102
|
+
Enable all tools with full access (default):
|
|
103
|
+
|
|
104
|
+
```bash
|
|
105
|
+
# No environment variables needed - all base groups enabled
|
|
106
|
+
```
|
|
107
|
+
|
|
108
|
+
Enable only newsletter tools:
|
|
109
|
+
|
|
110
|
+
```bash
|
|
111
|
+
TOOL_GROUPS=newsletter
|
|
112
|
+
```
|
|
113
|
+
|
|
114
|
+
Enable server_queue with read-only access:
|
|
115
|
+
|
|
116
|
+
```bash
|
|
117
|
+
TOOL_GROUPS=server_queue_readonly
|
|
118
|
+
```
|
|
119
|
+
|
|
120
|
+
Enable all groups with read-only access:
|
|
121
|
+
|
|
122
|
+
```bash
|
|
123
|
+
TOOL_GROUPS=newsletter_readonly,server_queue_readonly,official_queue_readonly
|
|
124
|
+
```
|
|
125
|
+
|
|
126
|
+
Mix full and read-only access per group:
|
|
127
|
+
|
|
128
|
+
```bash
|
|
129
|
+
# Full newsletter access, read-only server_queue, no official_queue
|
|
130
|
+
TOOL_GROUPS=newsletter,server_queue_readonly
|
|
131
|
+
```
|
|
75
132
|
|
|
76
133
|
# Usage Tips
|
|
77
134
|
|
|
@@ -83,7 +140,8 @@ You can control which tool groups are available by setting the `PULSEMCP_ADMIN_E
|
|
|
83
140
|
- Use author slugs when creating posts (e.g., "sarah-chen", "john-doe")
|
|
84
141
|
- Use MCP server/client slugs for featured content (e.g., "github-mcp", "claude-desktop")
|
|
85
142
|
- Use `search_mcp_implementations` to discover MCP servers and clients in the PulseMCP registry
|
|
86
|
-
- Enable or disable specific
|
|
143
|
+
- Enable or disable specific tool groups by setting `TOOL_GROUPS` environment variable
|
|
144
|
+
- Use `_readonly` suffixes to restrict groups to read-only operations (e.g., `server_queue_readonly`)
|
|
87
145
|
- Use the `remote` array parameter in `save_mcp_implementation` to configure remote endpoints for MCP servers (transport, host_platform, authentication_method, etc.)
|
|
88
146
|
- Use the `canonical` array parameter in `save_mcp_implementation` to set canonical URLs with scope (domain, subdomain, subfolder, or url)
|
|
89
147
|
- Remote endpoints allow specifying how MCP servers can be accessed (direct URL, setup URL, authentication method, cost, etc.)
|
|
@@ -194,7 +252,24 @@ Add to your Claude Desktop configuration:
|
|
|
194
252
|
"args": ["/path/to/pulsemcp-cms-admin/local/build/index.js"],
|
|
195
253
|
"env": {
|
|
196
254
|
"PULSEMCP_ADMIN_API_KEY": "your-api-key-here",
|
|
197
|
-
"
|
|
255
|
+
"TOOL_GROUPS": "newsletter,server_queue,official_queue"
|
|
256
|
+
}
|
|
257
|
+
}
|
|
258
|
+
}
|
|
259
|
+
}
|
|
260
|
+
```
|
|
261
|
+
|
|
262
|
+
For read-only access:
|
|
263
|
+
|
|
264
|
+
```json
|
|
265
|
+
{
|
|
266
|
+
"mcpServers": {
|
|
267
|
+
"pulsemcp-cms-admin-readonly": {
|
|
268
|
+
"command": "node",
|
|
269
|
+
"args": ["/path/to/pulsemcp-cms-admin/local/build/index.js"],
|
|
270
|
+
"env": {
|
|
271
|
+
"PULSEMCP_ADMIN_API_KEY": "your-api-key-here",
|
|
272
|
+
"TOOL_GROUPS": "newsletter_readonly,server_queue_readonly,official_queue_readonly"
|
|
198
273
|
}
|
|
199
274
|
}
|
|
200
275
|
}
|
|
@@ -18,65 +18,94 @@ import { rejectOfficialMirrorQueueItem } from './tools/reject-official-mirror-qu
|
|
|
18
18
|
import { addOfficialMirrorToRegularQueue } from './tools/add-official-mirror-to-regular-queue.js';
|
|
19
19
|
import { unlinkOfficialMirrorQueueItem } from './tools/unlink-official-mirror-queue-item.js';
|
|
20
20
|
const ALL_TOOLS = [
|
|
21
|
-
|
|
22
|
-
{ factory:
|
|
23
|
-
{ factory:
|
|
24
|
-
{ factory:
|
|
25
|
-
{ factory:
|
|
26
|
-
{ factory:
|
|
27
|
-
{ factory:
|
|
28
|
-
|
|
29
|
-
{ factory:
|
|
30
|
-
{ factory:
|
|
31
|
-
{ factory:
|
|
32
|
-
// Official mirror queue tools
|
|
21
|
+
// Newsletter tools (all are write operations except get_newsletter_posts/post and get_authors)
|
|
22
|
+
{ factory: getNewsletterPosts, group: 'newsletter', isWriteOperation: false },
|
|
23
|
+
{ factory: getNewsletterPost, group: 'newsletter', isWriteOperation: false },
|
|
24
|
+
{ factory: draftNewsletterPost, group: 'newsletter', isWriteOperation: true },
|
|
25
|
+
{ factory: updateNewsletterPost, group: 'newsletter', isWriteOperation: true },
|
|
26
|
+
{ factory: uploadImage, group: 'newsletter', isWriteOperation: true },
|
|
27
|
+
{ factory: getAuthors, group: 'newsletter', isWriteOperation: false },
|
|
28
|
+
// Server queue tools
|
|
29
|
+
{ factory: searchMCPImplementations, group: 'server_queue', isWriteOperation: false },
|
|
30
|
+
{ factory: getDraftMCPImplementations, group: 'server_queue', isWriteOperation: false },
|
|
31
|
+
{ factory: saveMCPImplementation, group: 'server_queue', isWriteOperation: true },
|
|
33
32
|
{
|
|
34
|
-
factory:
|
|
35
|
-
|
|
33
|
+
factory: sendMCPImplementationPostingNotification,
|
|
34
|
+
group: 'server_queue',
|
|
35
|
+
isWriteOperation: true,
|
|
36
36
|
},
|
|
37
|
+
{ factory: findProviders, group: 'server_queue', isWriteOperation: false },
|
|
38
|
+
// Official mirror queue tools
|
|
39
|
+
{ factory: getOfficialMirrorQueueItems, group: 'official_queue', isWriteOperation: false },
|
|
40
|
+
{ factory: getOfficialMirrorQueueItem, group: 'official_queue', isWriteOperation: false },
|
|
41
|
+
{ factory: approveOfficialMirrorQueueItem, group: 'official_queue', isWriteOperation: true },
|
|
37
42
|
{
|
|
38
|
-
factory:
|
|
39
|
-
|
|
43
|
+
factory: approveOfficialMirrorQueueItemWithoutModifying,
|
|
44
|
+
group: 'official_queue',
|
|
45
|
+
isWriteOperation: true,
|
|
40
46
|
},
|
|
41
|
-
{ factory:
|
|
42
|
-
{ factory:
|
|
43
|
-
{ factory:
|
|
44
|
-
|
|
45
|
-
|
|
47
|
+
{ factory: rejectOfficialMirrorQueueItem, group: 'official_queue', isWriteOperation: true },
|
|
48
|
+
{ factory: addOfficialMirrorToRegularQueue, group: 'official_queue', isWriteOperation: true },
|
|
49
|
+
{ factory: unlinkOfficialMirrorQueueItem, group: 'official_queue', isWriteOperation: true },
|
|
50
|
+
];
|
|
51
|
+
/**
|
|
52
|
+
* All valid tool groups (base groups and their _readonly variants)
|
|
53
|
+
*/
|
|
54
|
+
const VALID_TOOL_GROUPS = [
|
|
55
|
+
'newsletter',
|
|
56
|
+
'newsletter_readonly',
|
|
57
|
+
'server_queue',
|
|
58
|
+
'server_queue_readonly',
|
|
59
|
+
'official_queue',
|
|
60
|
+
'official_queue_readonly',
|
|
46
61
|
];
|
|
62
|
+
/**
|
|
63
|
+
* Base groups (without _readonly suffix) - used for default "all groups" behavior
|
|
64
|
+
*/
|
|
65
|
+
const BASE_TOOL_GROUPS = ['newsletter', 'server_queue', 'official_queue'];
|
|
47
66
|
/**
|
|
48
67
|
* Parse enabled tool groups from environment variable or parameter
|
|
49
|
-
* @param enabledGroupsParam - Comma-separated list of tool groups (e.g., "newsletter,
|
|
68
|
+
* @param enabledGroupsParam - Comma-separated list of tool groups (e.g., "newsletter,server_queue_readonly")
|
|
50
69
|
* @returns Array of enabled tool groups
|
|
51
70
|
*/
|
|
52
71
|
export function parseEnabledToolGroups(enabledGroupsParam) {
|
|
53
|
-
const groupsStr = enabledGroupsParam || process.env.
|
|
72
|
+
const groupsStr = enabledGroupsParam || process.env.TOOL_GROUPS || '';
|
|
54
73
|
if (!groupsStr) {
|
|
55
|
-
// Default: all groups enabled
|
|
56
|
-
return [
|
|
57
|
-
'newsletter',
|
|
58
|
-
'server_queue_readonly',
|
|
59
|
-
'server_queue_all',
|
|
60
|
-
'official_queue_readonly',
|
|
61
|
-
'official_queue_all',
|
|
62
|
-
];
|
|
74
|
+
// Default: all base groups enabled (full read+write access)
|
|
75
|
+
return [...BASE_TOOL_GROUPS];
|
|
63
76
|
}
|
|
64
77
|
const groups = groupsStr.split(',').map((g) => g.trim());
|
|
65
78
|
const validGroups = [];
|
|
66
79
|
for (const group of groups) {
|
|
67
|
-
if (group
|
|
68
|
-
group
|
|
69
|
-
group === 'server_queue_all' ||
|
|
70
|
-
group === 'official_queue_readonly' ||
|
|
71
|
-
group === 'official_queue_all') {
|
|
80
|
+
if (VALID_TOOL_GROUPS.includes(group) &&
|
|
81
|
+
!validGroups.includes(group)) {
|
|
72
82
|
validGroups.push(group);
|
|
73
83
|
}
|
|
74
|
-
else {
|
|
84
|
+
else if (!VALID_TOOL_GROUPS.includes(group)) {
|
|
75
85
|
console.warn(`Unknown tool group: ${group}`);
|
|
76
86
|
}
|
|
77
87
|
}
|
|
78
88
|
return validGroups;
|
|
79
89
|
}
|
|
90
|
+
/**
|
|
91
|
+
* Check if a tool should be included based on enabled groups
|
|
92
|
+
* @param toolDef - The tool definition to check
|
|
93
|
+
* @param enabledGroups - Array of enabled tool groups
|
|
94
|
+
* @returns true if the tool should be included
|
|
95
|
+
*/
|
|
96
|
+
function shouldIncludeTool(toolDef, enabledGroups) {
|
|
97
|
+
const baseGroup = toolDef.group;
|
|
98
|
+
const readonlyGroup = `${baseGroup}_readonly`;
|
|
99
|
+
// Check if the base group (full access) is enabled
|
|
100
|
+
if (enabledGroups.includes(baseGroup)) {
|
|
101
|
+
return true;
|
|
102
|
+
}
|
|
103
|
+
// Check if the readonly group is enabled (only include read operations)
|
|
104
|
+
if (enabledGroups.includes(readonlyGroup) && !toolDef.isWriteOperation) {
|
|
105
|
+
return true;
|
|
106
|
+
}
|
|
107
|
+
return false;
|
|
108
|
+
}
|
|
80
109
|
/**
|
|
81
110
|
* Creates a function to register all tools with the server.
|
|
82
111
|
* This pattern uses individual tool files for better modularity and testability.
|
|
@@ -84,16 +113,17 @@ export function parseEnabledToolGroups(enabledGroupsParam) {
|
|
|
84
113
|
* Each tool is defined in its own file under the `tools/` directory and follows
|
|
85
114
|
* a factory pattern that accepts the server and clientFactory as parameters.
|
|
86
115
|
*
|
|
87
|
-
* Tool groups can be enabled/disabled via the
|
|
88
|
-
*
|
|
89
|
-
*
|
|
116
|
+
* Tool groups can be enabled/disabled via the TOOL_GROUPS environment variable
|
|
117
|
+
* (comma-separated list, e.g., "newsletter,server_queue_readonly"). If not set, all
|
|
118
|
+
* base tool groups are enabled by default (full read+write access).
|
|
90
119
|
*
|
|
91
120
|
* Available tool groups:
|
|
92
|
-
* - newsletter: All newsletter-related tools
|
|
93
|
-
* -
|
|
94
|
-
* -
|
|
95
|
-
* -
|
|
96
|
-
* -
|
|
121
|
+
* - newsletter: All newsletter-related tools (read + write)
|
|
122
|
+
* - newsletter_readonly: Newsletter tools (read only)
|
|
123
|
+
* - server_queue: MCP implementation queue tools (read + write)
|
|
124
|
+
* - server_queue_readonly: MCP implementation queue tools (read only)
|
|
125
|
+
* - official_queue: Official mirror queue tools (read + write)
|
|
126
|
+
* - official_queue_readonly: Official mirror queue tools (read only)
|
|
97
127
|
*
|
|
98
128
|
* @param clientFactory - Factory function that creates client instances
|
|
99
129
|
* @param enabledGroups - Optional comma-separated list of enabled tool groups (overrides env var)
|
|
@@ -103,7 +133,7 @@ export function createRegisterTools(clientFactory, enabledGroups) {
|
|
|
103
133
|
return (server) => {
|
|
104
134
|
const enabledToolGroups = parseEnabledToolGroups(enabledGroups);
|
|
105
135
|
// Filter tools based on enabled groups
|
|
106
|
-
const enabledTools = ALL_TOOLS.filter((toolDef) => toolDef
|
|
136
|
+
const enabledTools = ALL_TOOLS.filter((toolDef) => shouldIncludeTool(toolDef, enabledToolGroups));
|
|
107
137
|
// Create tool instances
|
|
108
138
|
const tools = enabledTools.map((toolDef) => toolDef.factory(server, clientFactory));
|
|
109
139
|
// List available tools
|
package/package.json
CHANGED
package/shared/tools.d.ts
CHANGED
|
@@ -3,16 +3,19 @@ import { ClientFactory } from './server.js';
|
|
|
3
3
|
/**
|
|
4
4
|
* Tool group definitions - groups of related tools that can be enabled/disabled together
|
|
5
5
|
*
|
|
6
|
-
*
|
|
7
|
-
* -
|
|
8
|
-
* -
|
|
9
|
-
*
|
|
10
|
-
*
|
|
6
|
+
* Each group has two variants:
|
|
7
|
+
* - Base group (e.g., 'newsletter'): Includes all tools (read + write operations)
|
|
8
|
+
* - Readonly group (e.g., 'newsletter_readonly'): Includes only read operations
|
|
9
|
+
*
|
|
10
|
+
* Groups:
|
|
11
|
+
* - newsletter / newsletter_readonly: Newsletter-related tools (posts, authors, images)
|
|
12
|
+
* - server_queue / server_queue_readonly: Server queue tools (search, drafts, providers, save, notifications)
|
|
13
|
+
* - official_queue / official_queue_readonly: Official mirror queue tools (list, get, approve, reject, unlink)
|
|
11
14
|
*/
|
|
12
|
-
export type ToolGroup = 'newsletter' | '
|
|
15
|
+
export type ToolGroup = 'newsletter' | 'newsletter_readonly' | 'server_queue' | 'server_queue_readonly' | 'official_queue' | 'official_queue_readonly';
|
|
13
16
|
/**
|
|
14
17
|
* Parse enabled tool groups from environment variable or parameter
|
|
15
|
-
* @param enabledGroupsParam - Comma-separated list of tool groups (e.g., "newsletter,
|
|
18
|
+
* @param enabledGroupsParam - Comma-separated list of tool groups (e.g., "newsletter,server_queue_readonly")
|
|
16
19
|
* @returns Array of enabled tool groups
|
|
17
20
|
*/
|
|
18
21
|
export declare function parseEnabledToolGroups(enabledGroupsParam?: string): ToolGroup[];
|
|
@@ -23,16 +26,17 @@ export declare function parseEnabledToolGroups(enabledGroupsParam?: string): Too
|
|
|
23
26
|
* Each tool is defined in its own file under the `tools/` directory and follows
|
|
24
27
|
* a factory pattern that accepts the server and clientFactory as parameters.
|
|
25
28
|
*
|
|
26
|
-
* Tool groups can be enabled/disabled via the
|
|
27
|
-
*
|
|
28
|
-
*
|
|
29
|
+
* Tool groups can be enabled/disabled via the TOOL_GROUPS environment variable
|
|
30
|
+
* (comma-separated list, e.g., "newsletter,server_queue_readonly"). If not set, all
|
|
31
|
+
* base tool groups are enabled by default (full read+write access).
|
|
29
32
|
*
|
|
30
33
|
* Available tool groups:
|
|
31
|
-
* - newsletter: All newsletter-related tools
|
|
32
|
-
* -
|
|
33
|
-
* -
|
|
34
|
-
* -
|
|
35
|
-
* -
|
|
34
|
+
* - newsletter: All newsletter-related tools (read + write)
|
|
35
|
+
* - newsletter_readonly: Newsletter tools (read only)
|
|
36
|
+
* - server_queue: MCP implementation queue tools (read + write)
|
|
37
|
+
* - server_queue_readonly: MCP implementation queue tools (read only)
|
|
38
|
+
* - official_queue: Official mirror queue tools (read + write)
|
|
39
|
+
* - official_queue_readonly: Official mirror queue tools (read only)
|
|
36
40
|
*
|
|
37
41
|
* @param clientFactory - Factory function that creates client instances
|
|
38
42
|
* @param enabledGroups - Optional comma-separated list of enabled tool groups (overrides env var)
|
package/shared/tools.js
CHANGED
|
@@ -18,65 +18,94 @@ import { rejectOfficialMirrorQueueItem } from './tools/reject-official-mirror-qu
|
|
|
18
18
|
import { addOfficialMirrorToRegularQueue } from './tools/add-official-mirror-to-regular-queue.js';
|
|
19
19
|
import { unlinkOfficialMirrorQueueItem } from './tools/unlink-official-mirror-queue-item.js';
|
|
20
20
|
const ALL_TOOLS = [
|
|
21
|
-
|
|
22
|
-
{ factory:
|
|
23
|
-
{ factory:
|
|
24
|
-
{ factory:
|
|
25
|
-
{ factory:
|
|
26
|
-
{ factory:
|
|
27
|
-
{ factory:
|
|
28
|
-
|
|
29
|
-
{ factory:
|
|
30
|
-
{ factory:
|
|
31
|
-
{ factory:
|
|
32
|
-
// Official mirror queue tools
|
|
21
|
+
// Newsletter tools (all are write operations except get_newsletter_posts/post and get_authors)
|
|
22
|
+
{ factory: getNewsletterPosts, group: 'newsletter', isWriteOperation: false },
|
|
23
|
+
{ factory: getNewsletterPost, group: 'newsletter', isWriteOperation: false },
|
|
24
|
+
{ factory: draftNewsletterPost, group: 'newsletter', isWriteOperation: true },
|
|
25
|
+
{ factory: updateNewsletterPost, group: 'newsletter', isWriteOperation: true },
|
|
26
|
+
{ factory: uploadImage, group: 'newsletter', isWriteOperation: true },
|
|
27
|
+
{ factory: getAuthors, group: 'newsletter', isWriteOperation: false },
|
|
28
|
+
// Server queue tools
|
|
29
|
+
{ factory: searchMCPImplementations, group: 'server_queue', isWriteOperation: false },
|
|
30
|
+
{ factory: getDraftMCPImplementations, group: 'server_queue', isWriteOperation: false },
|
|
31
|
+
{ factory: saveMCPImplementation, group: 'server_queue', isWriteOperation: true },
|
|
33
32
|
{
|
|
34
|
-
factory:
|
|
35
|
-
|
|
33
|
+
factory: sendMCPImplementationPostingNotification,
|
|
34
|
+
group: 'server_queue',
|
|
35
|
+
isWriteOperation: true,
|
|
36
36
|
},
|
|
37
|
+
{ factory: findProviders, group: 'server_queue', isWriteOperation: false },
|
|
38
|
+
// Official mirror queue tools
|
|
39
|
+
{ factory: getOfficialMirrorQueueItems, group: 'official_queue', isWriteOperation: false },
|
|
40
|
+
{ factory: getOfficialMirrorQueueItem, group: 'official_queue', isWriteOperation: false },
|
|
41
|
+
{ factory: approveOfficialMirrorQueueItem, group: 'official_queue', isWriteOperation: true },
|
|
37
42
|
{
|
|
38
|
-
factory:
|
|
39
|
-
|
|
43
|
+
factory: approveOfficialMirrorQueueItemWithoutModifying,
|
|
44
|
+
group: 'official_queue',
|
|
45
|
+
isWriteOperation: true,
|
|
40
46
|
},
|
|
41
|
-
{ factory:
|
|
42
|
-
{ factory:
|
|
43
|
-
{ factory:
|
|
44
|
-
|
|
45
|
-
|
|
47
|
+
{ factory: rejectOfficialMirrorQueueItem, group: 'official_queue', isWriteOperation: true },
|
|
48
|
+
{ factory: addOfficialMirrorToRegularQueue, group: 'official_queue', isWriteOperation: true },
|
|
49
|
+
{ factory: unlinkOfficialMirrorQueueItem, group: 'official_queue', isWriteOperation: true },
|
|
50
|
+
];
|
|
51
|
+
/**
|
|
52
|
+
* All valid tool groups (base groups and their _readonly variants)
|
|
53
|
+
*/
|
|
54
|
+
const VALID_TOOL_GROUPS = [
|
|
55
|
+
'newsletter',
|
|
56
|
+
'newsletter_readonly',
|
|
57
|
+
'server_queue',
|
|
58
|
+
'server_queue_readonly',
|
|
59
|
+
'official_queue',
|
|
60
|
+
'official_queue_readonly',
|
|
46
61
|
];
|
|
62
|
+
/**
|
|
63
|
+
* Base groups (without _readonly suffix) - used for default "all groups" behavior
|
|
64
|
+
*/
|
|
65
|
+
const BASE_TOOL_GROUPS = ['newsletter', 'server_queue', 'official_queue'];
|
|
47
66
|
/**
|
|
48
67
|
* Parse enabled tool groups from environment variable or parameter
|
|
49
|
-
* @param enabledGroupsParam - Comma-separated list of tool groups (e.g., "newsletter,
|
|
68
|
+
* @param enabledGroupsParam - Comma-separated list of tool groups (e.g., "newsletter,server_queue_readonly")
|
|
50
69
|
* @returns Array of enabled tool groups
|
|
51
70
|
*/
|
|
52
71
|
export function parseEnabledToolGroups(enabledGroupsParam) {
|
|
53
|
-
const groupsStr = enabledGroupsParam || process.env.
|
|
72
|
+
const groupsStr = enabledGroupsParam || process.env.TOOL_GROUPS || '';
|
|
54
73
|
if (!groupsStr) {
|
|
55
|
-
// Default: all groups enabled
|
|
56
|
-
return [
|
|
57
|
-
'newsletter',
|
|
58
|
-
'server_queue_readonly',
|
|
59
|
-
'server_queue_all',
|
|
60
|
-
'official_queue_readonly',
|
|
61
|
-
'official_queue_all',
|
|
62
|
-
];
|
|
74
|
+
// Default: all base groups enabled (full read+write access)
|
|
75
|
+
return [...BASE_TOOL_GROUPS];
|
|
63
76
|
}
|
|
64
77
|
const groups = groupsStr.split(',').map((g) => g.trim());
|
|
65
78
|
const validGroups = [];
|
|
66
79
|
for (const group of groups) {
|
|
67
|
-
if (group
|
|
68
|
-
group
|
|
69
|
-
group === 'server_queue_all' ||
|
|
70
|
-
group === 'official_queue_readonly' ||
|
|
71
|
-
group === 'official_queue_all') {
|
|
80
|
+
if (VALID_TOOL_GROUPS.includes(group) &&
|
|
81
|
+
!validGroups.includes(group)) {
|
|
72
82
|
validGroups.push(group);
|
|
73
83
|
}
|
|
74
|
-
else {
|
|
84
|
+
else if (!VALID_TOOL_GROUPS.includes(group)) {
|
|
75
85
|
console.warn(`Unknown tool group: ${group}`);
|
|
76
86
|
}
|
|
77
87
|
}
|
|
78
88
|
return validGroups;
|
|
79
89
|
}
|
|
90
|
+
/**
|
|
91
|
+
* Check if a tool should be included based on enabled groups
|
|
92
|
+
* @param toolDef - The tool definition to check
|
|
93
|
+
* @param enabledGroups - Array of enabled tool groups
|
|
94
|
+
* @returns true if the tool should be included
|
|
95
|
+
*/
|
|
96
|
+
function shouldIncludeTool(toolDef, enabledGroups) {
|
|
97
|
+
const baseGroup = toolDef.group;
|
|
98
|
+
const readonlyGroup = `${baseGroup}_readonly`;
|
|
99
|
+
// Check if the base group (full access) is enabled
|
|
100
|
+
if (enabledGroups.includes(baseGroup)) {
|
|
101
|
+
return true;
|
|
102
|
+
}
|
|
103
|
+
// Check if the readonly group is enabled (only include read operations)
|
|
104
|
+
if (enabledGroups.includes(readonlyGroup) && !toolDef.isWriteOperation) {
|
|
105
|
+
return true;
|
|
106
|
+
}
|
|
107
|
+
return false;
|
|
108
|
+
}
|
|
80
109
|
/**
|
|
81
110
|
* Creates a function to register all tools with the server.
|
|
82
111
|
* This pattern uses individual tool files for better modularity and testability.
|
|
@@ -84,16 +113,17 @@ export function parseEnabledToolGroups(enabledGroupsParam) {
|
|
|
84
113
|
* Each tool is defined in its own file under the `tools/` directory and follows
|
|
85
114
|
* a factory pattern that accepts the server and clientFactory as parameters.
|
|
86
115
|
*
|
|
87
|
-
* Tool groups can be enabled/disabled via the
|
|
88
|
-
*
|
|
89
|
-
*
|
|
116
|
+
* Tool groups can be enabled/disabled via the TOOL_GROUPS environment variable
|
|
117
|
+
* (comma-separated list, e.g., "newsletter,server_queue_readonly"). If not set, all
|
|
118
|
+
* base tool groups are enabled by default (full read+write access).
|
|
90
119
|
*
|
|
91
120
|
* Available tool groups:
|
|
92
|
-
* - newsletter: All newsletter-related tools
|
|
93
|
-
* -
|
|
94
|
-
* -
|
|
95
|
-
* -
|
|
96
|
-
* -
|
|
121
|
+
* - newsletter: All newsletter-related tools (read + write)
|
|
122
|
+
* - newsletter_readonly: Newsletter tools (read only)
|
|
123
|
+
* - server_queue: MCP implementation queue tools (read + write)
|
|
124
|
+
* - server_queue_readonly: MCP implementation queue tools (read only)
|
|
125
|
+
* - official_queue: Official mirror queue tools (read + write)
|
|
126
|
+
* - official_queue_readonly: Official mirror queue tools (read only)
|
|
97
127
|
*
|
|
98
128
|
* @param clientFactory - Factory function that creates client instances
|
|
99
129
|
* @param enabledGroups - Optional comma-separated list of enabled tool groups (overrides env var)
|
|
@@ -103,7 +133,7 @@ export function createRegisterTools(clientFactory, enabledGroups) {
|
|
|
103
133
|
return (server) => {
|
|
104
134
|
const enabledToolGroups = parseEnabledToolGroups(enabledGroups);
|
|
105
135
|
// Filter tools based on enabled groups
|
|
106
|
-
const enabledTools = ALL_TOOLS.filter((toolDef) => toolDef
|
|
136
|
+
const enabledTools = ALL_TOOLS.filter((toolDef) => shouldIncludeTool(toolDef, enabledToolGroups));
|
|
107
137
|
// Create tool instances
|
|
108
138
|
const tools = enabledTools.map((toolDef) => toolDef.factory(server, clientFactory));
|
|
109
139
|
// List available tools
|