pulsemcp-cms-admin-mcp-server 0.9.2 → 0.9.6

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.
@@ -56,6 +56,8 @@ export async function getProctorRuns(apiKey, baseUrl, params) {
56
56
  num_tools: run.num_tools,
57
57
  packages: run.packages,
58
58
  remotes: run.remotes,
59
+ known_missing_init_tools_list: run.known_missing_init_tools_list || false,
60
+ known_missing_auth_check: run.known_missing_auth_check || false,
59
61
  })),
60
62
  pagination: {
61
63
  current_page: data.meta.current_page,
@@ -1,5 +1,72 @@
1
1
  import { Server } from '@modelcontextprotocol/sdk/server/index.js';
2
2
  import { createRegisterTools } from './tools.js';
3
+ // Static imports for all API client functions (replaces dynamic imports
4
+ // which can fail at runtime in some environments due to ESM resolution)
5
+ import { getPosts } from './pulsemcp-admin-client/lib/get-posts.js';
6
+ import { getPost } from './pulsemcp-admin-client/lib/get-post.js';
7
+ import { createPost } from './pulsemcp-admin-client/lib/create-post.js';
8
+ import { updatePost } from './pulsemcp-admin-client/lib/update-post.js';
9
+ import { uploadImage } from './pulsemcp-admin-client/lib/upload-image.js';
10
+ import { getAuthors } from './pulsemcp-admin-client/lib/get-authors.js';
11
+ import { getAuthorBySlug } from './pulsemcp-admin-client/lib/get-author-by-slug.js';
12
+ import { getAuthorById } from './pulsemcp-admin-client/lib/get-author-by-id.js';
13
+ import { getMCPServerBySlug } from './pulsemcp-admin-client/lib/get-mcp-server-by-slug.js';
14
+ import { getMCPServerById } from './pulsemcp-admin-client/lib/get-mcp-server-by-id.js';
15
+ import { getMCPClientBySlug } from './pulsemcp-admin-client/lib/get-mcp-client-by-slug.js';
16
+ import { getMCPClientById } from './pulsemcp-admin-client/lib/get-mcp-client-by-id.js';
17
+ import { getMCPImplementationById } from './pulsemcp-admin-client/lib/get-mcp-implementation-by-id.js';
18
+ import { searchMCPImplementations } from './pulsemcp-admin-client/lib/search-mcp-implementations.js';
19
+ import { getDraftMCPImplementations } from './pulsemcp-admin-client/lib/get-draft-mcp-implementations.js';
20
+ import { saveMCPImplementation } from './pulsemcp-admin-client/lib/save-mcp-implementation.js';
21
+ import { createMCPImplementation } from './pulsemcp-admin-client/lib/create-mcp-implementation.js';
22
+ import { sendEmail } from './pulsemcp-admin-client/lib/send-email.js';
23
+ import { searchProviders } from './pulsemcp-admin-client/lib/search-providers.js';
24
+ import { getProviderById } from './pulsemcp-admin-client/lib/get-provider-by-id.js';
25
+ import { getOfficialMirrorQueueItems } from './pulsemcp-admin-client/lib/get-official-mirror-queue-items.js';
26
+ import { getOfficialMirrorQueueItem } from './pulsemcp-admin-client/lib/get-official-mirror-queue-item.js';
27
+ import { approveOfficialMirrorQueueItem } from './pulsemcp-admin-client/lib/approve-official-mirror-queue-item.js';
28
+ import { approveOfficialMirrorQueueItemWithoutModifying } from './pulsemcp-admin-client/lib/approve-official-mirror-queue-item-without-modifying.js';
29
+ import { rejectOfficialMirrorQueueItem } from './pulsemcp-admin-client/lib/reject-official-mirror-queue-item.js';
30
+ import { addOfficialMirrorToRegularQueue } from './pulsemcp-admin-client/lib/add-official-mirror-to-regular-queue.js';
31
+ import { unlinkOfficialMirrorQueueItem } from './pulsemcp-admin-client/lib/unlink-official-mirror-queue-item.js';
32
+ import { getUnofficialMirrors } from './pulsemcp-admin-client/lib/get-unofficial-mirrors.js';
33
+ import { getUnofficialMirror } from './pulsemcp-admin-client/lib/get-unofficial-mirror.js';
34
+ import { createUnofficialMirror } from './pulsemcp-admin-client/lib/create-unofficial-mirror.js';
35
+ import { updateUnofficialMirror } from './pulsemcp-admin-client/lib/update-unofficial-mirror.js';
36
+ import { deleteUnofficialMirror } from './pulsemcp-admin-client/lib/delete-unofficial-mirror.js';
37
+ import { getOfficialMirrors } from './pulsemcp-admin-client/lib/get-official-mirrors.js';
38
+ import { getOfficialMirror } from './pulsemcp-admin-client/lib/get-official-mirror.js';
39
+ import { getTenants } from './pulsemcp-admin-client/lib/get-tenants.js';
40
+ import { getTenant } from './pulsemcp-admin-client/lib/get-tenant.js';
41
+ import { getMcpJsons } from './pulsemcp-admin-client/lib/get-mcp-jsons.js';
42
+ import { getMcpJson } from './pulsemcp-admin-client/lib/get-mcp-json.js';
43
+ import { createMcpJson } from './pulsemcp-admin-client/lib/create-mcp-json.js';
44
+ import { updateMcpJson } from './pulsemcp-admin-client/lib/update-mcp-json.js';
45
+ import { deleteMcpJson } from './pulsemcp-admin-client/lib/delete-mcp-json.js';
46
+ import { getUnifiedMCPServers } from './pulsemcp-admin-client/lib/get-unified-mcp-servers.js';
47
+ import { getUnifiedMCPServer } from './pulsemcp-admin-client/lib/get-unified-mcp-server.js';
48
+ import { updateUnifiedMCPServer } from './pulsemcp-admin-client/lib/update-unified-mcp-server.js';
49
+ import { getRedirects } from './pulsemcp-admin-client/lib/get-redirects.js';
50
+ import { getRedirect } from './pulsemcp-admin-client/lib/get-redirect.js';
51
+ import { createRedirect } from './pulsemcp-admin-client/lib/create-redirect.js';
52
+ import { updateRedirect } from './pulsemcp-admin-client/lib/update-redirect.js';
53
+ import { deleteRedirect } from './pulsemcp-admin-client/lib/delete-redirect.js';
54
+ import { getGoodJobs } from './pulsemcp-admin-client/lib/get-good-jobs.js';
55
+ import { getGoodJob } from './pulsemcp-admin-client/lib/get-good-job.js';
56
+ import { getGoodJobCronSchedules } from './pulsemcp-admin-client/lib/get-good-job-cron-schedules.js';
57
+ import { getGoodJobProcesses } from './pulsemcp-admin-client/lib/get-good-job-processes.js';
58
+ import { getGoodJobStatistics } from './pulsemcp-admin-client/lib/get-good-job-statistics.js';
59
+ import { retryGoodJob } from './pulsemcp-admin-client/lib/retry-good-job.js';
60
+ import { discardGoodJob } from './pulsemcp-admin-client/lib/discard-good-job.js';
61
+ import { rescheduleGoodJob } from './pulsemcp-admin-client/lib/reschedule-good-job.js';
62
+ import { forceTriggerGoodJobCron } from './pulsemcp-admin-client/lib/force-trigger-good-job-cron.js';
63
+ import { cleanupGoodJobs } from './pulsemcp-admin-client/lib/cleanup-good-jobs.js';
64
+ import { runExamForMirror } from './pulsemcp-admin-client/lib/run-exam-for-mirror.js';
65
+ import { saveResultsForMirror } from './pulsemcp-admin-client/lib/save-results-for-mirror.js';
66
+ import { getProctorRuns } from './pulsemcp-admin-client/lib/get-proctor-runs.js';
67
+ import { getDiscoveredUrls } from './pulsemcp-admin-client/lib/get-discovered-urls.js';
68
+ import { markDiscoveredUrlProcessed } from './pulsemcp-admin-client/lib/mark-discovered-url-processed.js';
69
+ import { getDiscoveredUrlStats } from './pulsemcp-admin-client/lib/get-discovered-url-stats.js';
3
70
  // PulseMCP Admin API client implementation
4
71
  export class PulseMCPAdminClient {
5
72
  apiKey;
@@ -9,273 +76,208 @@ export class PulseMCPAdminClient {
9
76
  this.baseUrl = baseUrl || 'https://admin.pulsemcp.com';
10
77
  }
11
78
  async getPosts(params) {
12
- const { getPosts } = await import('./pulsemcp-admin-client/lib/get-posts.js');
13
79
  return getPosts(this.apiKey, this.baseUrl, params);
14
80
  }
15
81
  async getPost(slug) {
16
- const { getPost } = await import('./pulsemcp-admin-client/lib/get-post.js');
17
82
  return getPost(this.apiKey, this.baseUrl, slug);
18
83
  }
19
84
  async createPost(params) {
20
- const { createPost } = await import('./pulsemcp-admin-client/lib/create-post.js');
21
85
  return createPost(this.apiKey, this.baseUrl, params);
22
86
  }
23
87
  async updatePost(slug, params) {
24
- const { updatePost } = await import('./pulsemcp-admin-client/lib/update-post.js');
25
88
  return updatePost(this.apiKey, this.baseUrl, slug, params);
26
89
  }
27
90
  async uploadImage(postSlug, fileName, fileData) {
28
- const { uploadImage } = await import('./pulsemcp-admin-client/lib/upload-image.js');
29
91
  return uploadImage(this.apiKey, this.baseUrl, postSlug, fileName, fileData);
30
92
  }
31
93
  async getAuthors(params) {
32
- const { getAuthors } = await import('./pulsemcp-admin-client/lib/get-authors.js');
33
94
  return getAuthors(this.apiKey, this.baseUrl, params);
34
95
  }
35
96
  async getAuthorBySlug(slug) {
36
- const { getAuthorBySlug } = await import('./pulsemcp-admin-client/lib/get-author-by-slug.js');
37
97
  return getAuthorBySlug(this.apiKey, this.baseUrl, slug);
38
98
  }
39
99
  async getAuthorById(id) {
40
- const { getAuthorById } = await import('./pulsemcp-admin-client/lib/get-author-by-id.js');
41
100
  return getAuthorById(this.apiKey, this.baseUrl, id);
42
101
  }
43
102
  async getMCPServerBySlug(slug) {
44
- const { getMCPServerBySlug } = await import('./pulsemcp-admin-client/lib/get-mcp-server-by-slug.js');
45
103
  return getMCPServerBySlug(this.apiKey, this.baseUrl, slug);
46
104
  }
47
105
  async getMCPServerById(id) {
48
- const { getMCPServerById } = await import('./pulsemcp-admin-client/lib/get-mcp-server-by-id.js');
49
106
  return getMCPServerById(this.apiKey, this.baseUrl, id);
50
107
  }
51
108
  async getMCPClientBySlug(slug) {
52
- const { getMCPClientBySlug } = await import('./pulsemcp-admin-client/lib/get-mcp-client-by-slug.js');
53
109
  return getMCPClientBySlug(this.apiKey, this.baseUrl, slug);
54
110
  }
55
111
  async getMCPClientById(id) {
56
- const { getMCPClientById } = await import('./pulsemcp-admin-client/lib/get-mcp-client-by-id.js');
57
112
  return getMCPClientById(this.apiKey, this.baseUrl, id);
58
113
  }
59
114
  async getMCPImplementationById(id) {
60
- const { getMCPImplementationById } = await import('./pulsemcp-admin-client/lib/get-mcp-implementation-by-id.js');
61
115
  return getMCPImplementationById(this.apiKey, this.baseUrl, id);
62
116
  }
63
117
  async searchMCPImplementations(params) {
64
- const { searchMCPImplementations } = await import('./pulsemcp-admin-client/lib/search-mcp-implementations.js');
65
118
  return searchMCPImplementations(this.apiKey, this.baseUrl, params);
66
119
  }
67
120
  async getDraftMCPImplementations(params) {
68
- const { getDraftMCPImplementations } = await import('./pulsemcp-admin-client/lib/get-draft-mcp-implementations.js');
69
121
  return getDraftMCPImplementations(this.apiKey, this.baseUrl, params);
70
122
  }
71
123
  async saveMCPImplementation(id, params) {
72
- const { saveMCPImplementation } = await import('./pulsemcp-admin-client/lib/save-mcp-implementation.js');
73
124
  return saveMCPImplementation(this.apiKey, this.baseUrl, id, params);
74
125
  }
75
126
  async createMCPImplementation(params) {
76
- const { createMCPImplementation } = await import('./pulsemcp-admin-client/lib/create-mcp-implementation.js');
77
127
  return createMCPImplementation(this.apiKey, this.baseUrl, params);
78
128
  }
79
129
  async sendEmail(params) {
80
- const { sendEmail } = await import('./pulsemcp-admin-client/lib/send-email.js');
81
130
  return sendEmail(this.apiKey, this.baseUrl, params);
82
131
  }
83
132
  async searchProviders(params) {
84
- const { searchProviders } = await import('./pulsemcp-admin-client/lib/search-providers.js');
85
133
  return searchProviders(this.apiKey, this.baseUrl, params);
86
134
  }
87
135
  async getProviderById(id) {
88
- const { getProviderById } = await import('./pulsemcp-admin-client/lib/get-provider-by-id.js');
89
136
  return getProviderById(this.apiKey, this.baseUrl, id);
90
137
  }
91
138
  // Official Mirror Queue methods
92
139
  async getOfficialMirrorQueueItems(params) {
93
- const { getOfficialMirrorQueueItems } = await import('./pulsemcp-admin-client/lib/get-official-mirror-queue-items.js');
94
140
  return getOfficialMirrorQueueItems(this.apiKey, this.baseUrl, params);
95
141
  }
96
142
  async getOfficialMirrorQueueItem(id) {
97
- const { getOfficialMirrorQueueItem } = await import('./pulsemcp-admin-client/lib/get-official-mirror-queue-item.js');
98
143
  return getOfficialMirrorQueueItem(this.apiKey, this.baseUrl, id);
99
144
  }
100
145
  async approveOfficialMirrorQueueItem(id, mcpServerSlug) {
101
- const { approveOfficialMirrorQueueItem } = await import('./pulsemcp-admin-client/lib/approve-official-mirror-queue-item.js');
102
146
  return approveOfficialMirrorQueueItem(this.apiKey, this.baseUrl, id, mcpServerSlug);
103
147
  }
104
148
  async approveOfficialMirrorQueueItemWithoutModifying(id) {
105
- const { approveOfficialMirrorQueueItemWithoutModifying } = await import('./pulsemcp-admin-client/lib/approve-official-mirror-queue-item-without-modifying.js');
106
149
  return approveOfficialMirrorQueueItemWithoutModifying(this.apiKey, this.baseUrl, id);
107
150
  }
108
151
  async rejectOfficialMirrorQueueItem(id) {
109
- const { rejectOfficialMirrorQueueItem } = await import('./pulsemcp-admin-client/lib/reject-official-mirror-queue-item.js');
110
152
  return rejectOfficialMirrorQueueItem(this.apiKey, this.baseUrl, id);
111
153
  }
112
154
  async addOfficialMirrorToRegularQueue(id) {
113
- const { addOfficialMirrorToRegularQueue } = await import('./pulsemcp-admin-client/lib/add-official-mirror-to-regular-queue.js');
114
155
  return addOfficialMirrorToRegularQueue(this.apiKey, this.baseUrl, id);
115
156
  }
116
157
  async unlinkOfficialMirrorQueueItem(id) {
117
- const { unlinkOfficialMirrorQueueItem } = await import('./pulsemcp-admin-client/lib/unlink-official-mirror-queue-item.js');
118
158
  return unlinkOfficialMirrorQueueItem(this.apiKey, this.baseUrl, id);
119
159
  }
120
160
  // Unofficial Mirror REST API methods
121
161
  async getUnofficialMirrors(params) {
122
- const { getUnofficialMirrors } = await import('./pulsemcp-admin-client/lib/get-unofficial-mirrors.js');
123
162
  return getUnofficialMirrors(this.apiKey, this.baseUrl, params);
124
163
  }
125
164
  async getUnofficialMirror(id) {
126
- const { getUnofficialMirror } = await import('./pulsemcp-admin-client/lib/get-unofficial-mirror.js');
127
165
  return getUnofficialMirror(this.apiKey, this.baseUrl, id);
128
166
  }
129
167
  async createUnofficialMirror(params) {
130
- const { createUnofficialMirror } = await import('./pulsemcp-admin-client/lib/create-unofficial-mirror.js');
131
168
  return createUnofficialMirror(this.apiKey, this.baseUrl, params);
132
169
  }
133
170
  async updateUnofficialMirror(id, params) {
134
- const { updateUnofficialMirror } = await import('./pulsemcp-admin-client/lib/update-unofficial-mirror.js');
135
171
  return updateUnofficialMirror(this.apiKey, this.baseUrl, id, params);
136
172
  }
137
173
  async deleteUnofficialMirror(id) {
138
- const { deleteUnofficialMirror } = await import('./pulsemcp-admin-client/lib/delete-unofficial-mirror.js');
139
174
  return deleteUnofficialMirror(this.apiKey, this.baseUrl, id);
140
175
  }
141
176
  // Official Mirror REST API methods (read-only)
142
177
  async getOfficialMirrors(params) {
143
- const { getOfficialMirrors } = await import('./pulsemcp-admin-client/lib/get-official-mirrors.js');
144
178
  return getOfficialMirrors(this.apiKey, this.baseUrl, params);
145
179
  }
146
180
  async getOfficialMirror(id) {
147
- const { getOfficialMirror } = await import('./pulsemcp-admin-client/lib/get-official-mirror.js');
148
181
  return getOfficialMirror(this.apiKey, this.baseUrl, id);
149
182
  }
150
183
  // Tenant REST API methods (read-only)
151
184
  async getTenants(params) {
152
- const { getTenants } = await import('./pulsemcp-admin-client/lib/get-tenants.js');
153
185
  return getTenants(this.apiKey, this.baseUrl, params);
154
186
  }
155
187
  async getTenant(idOrSlug) {
156
- const { getTenant } = await import('./pulsemcp-admin-client/lib/get-tenant.js');
157
188
  return getTenant(this.apiKey, this.baseUrl, idOrSlug);
158
189
  }
159
190
  // MCP JSON REST API methods
160
191
  async getMcpJsons(params) {
161
- const { getMcpJsons } = await import('./pulsemcp-admin-client/lib/get-mcp-jsons.js');
162
192
  return getMcpJsons(this.apiKey, this.baseUrl, params);
163
193
  }
164
194
  async getMcpJson(id) {
165
- const { getMcpJson } = await import('./pulsemcp-admin-client/lib/get-mcp-json.js');
166
195
  return getMcpJson(this.apiKey, this.baseUrl, id);
167
196
  }
168
197
  async createMcpJson(params) {
169
- const { createMcpJson } = await import('./pulsemcp-admin-client/lib/create-mcp-json.js');
170
198
  return createMcpJson(this.apiKey, this.baseUrl, params);
171
199
  }
172
200
  async updateMcpJson(id, params) {
173
- const { updateMcpJson } = await import('./pulsemcp-admin-client/lib/update-mcp-json.js');
174
201
  return updateMcpJson(this.apiKey, this.baseUrl, id, params);
175
202
  }
176
203
  async deleteMcpJson(id) {
177
- const { deleteMcpJson } = await import('./pulsemcp-admin-client/lib/delete-mcp-json.js');
178
204
  return deleteMcpJson(this.apiKey, this.baseUrl, id);
179
205
  }
180
206
  // Unified MCP Server methods (abstracted interface)
181
207
  async getUnifiedMCPServers(params) {
182
- const { getUnifiedMCPServers } = await import('./pulsemcp-admin-client/lib/get-unified-mcp-servers.js');
183
208
  return getUnifiedMCPServers(this.apiKey, this.baseUrl, params);
184
209
  }
185
210
  async getUnifiedMCPServer(slug) {
186
- const { getUnifiedMCPServer } = await import('./pulsemcp-admin-client/lib/get-unified-mcp-server.js');
187
211
  return getUnifiedMCPServer(this.apiKey, this.baseUrl, slug);
188
212
  }
189
213
  async updateUnifiedMCPServer(implementationId, params) {
190
- const { updateUnifiedMCPServer } = await import('./pulsemcp-admin-client/lib/update-unified-mcp-server.js');
191
214
  return updateUnifiedMCPServer(this.apiKey, this.baseUrl, implementationId, params);
192
215
  }
193
216
  // Redirect REST API methods
194
217
  async getRedirects(params) {
195
- const { getRedirects } = await import('./pulsemcp-admin-client/lib/get-redirects.js');
196
218
  return getRedirects(this.apiKey, this.baseUrl, params);
197
219
  }
198
220
  async getRedirect(id) {
199
- const { getRedirect } = await import('./pulsemcp-admin-client/lib/get-redirect.js');
200
221
  return getRedirect(this.apiKey, this.baseUrl, id);
201
222
  }
202
223
  async createRedirect(params) {
203
- const { createRedirect } = await import('./pulsemcp-admin-client/lib/create-redirect.js');
204
224
  return createRedirect(this.apiKey, this.baseUrl, params);
205
225
  }
206
226
  async updateRedirect(id, params) {
207
- const { updateRedirect } = await import('./pulsemcp-admin-client/lib/update-redirect.js');
208
227
  return updateRedirect(this.apiKey, this.baseUrl, id, params);
209
228
  }
210
229
  async deleteRedirect(id) {
211
- const { deleteRedirect } = await import('./pulsemcp-admin-client/lib/delete-redirect.js');
212
230
  return deleteRedirect(this.apiKey, this.baseUrl, id);
213
231
  }
214
232
  // GoodJob REST API methods
215
233
  async getGoodJobs(params) {
216
- const { getGoodJobs } = await import('./pulsemcp-admin-client/lib/get-good-jobs.js');
217
234
  return getGoodJobs(this.apiKey, this.baseUrl, params);
218
235
  }
219
236
  async getGoodJob(id) {
220
- const { getGoodJob } = await import('./pulsemcp-admin-client/lib/get-good-job.js');
221
237
  return getGoodJob(this.apiKey, this.baseUrl, id);
222
238
  }
223
239
  async getGoodJobCronSchedules() {
224
- const { getGoodJobCronSchedules } = await import('./pulsemcp-admin-client/lib/get-good-job-cron-schedules.js');
225
240
  return getGoodJobCronSchedules(this.apiKey, this.baseUrl);
226
241
  }
227
242
  async getGoodJobProcesses() {
228
- const { getGoodJobProcesses } = await import('./pulsemcp-admin-client/lib/get-good-job-processes.js');
229
243
  return getGoodJobProcesses(this.apiKey, this.baseUrl);
230
244
  }
231
245
  async getGoodJobStatistics() {
232
- const { getGoodJobStatistics } = await import('./pulsemcp-admin-client/lib/get-good-job-statistics.js');
233
246
  return getGoodJobStatistics(this.apiKey, this.baseUrl);
234
247
  }
235
248
  async retryGoodJob(id) {
236
- const { retryGoodJob } = await import('./pulsemcp-admin-client/lib/retry-good-job.js');
237
249
  return retryGoodJob(this.apiKey, this.baseUrl, id);
238
250
  }
239
251
  async discardGoodJob(id) {
240
- const { discardGoodJob } = await import('./pulsemcp-admin-client/lib/discard-good-job.js');
241
252
  return discardGoodJob(this.apiKey, this.baseUrl, id);
242
253
  }
243
254
  async rescheduleGoodJob(id, scheduledAt) {
244
- const { rescheduleGoodJob } = await import('./pulsemcp-admin-client/lib/reschedule-good-job.js');
245
255
  return rescheduleGoodJob(this.apiKey, this.baseUrl, id, scheduledAt);
246
256
  }
247
257
  async forceTriggerGoodJobCron(cronKey) {
248
- const { forceTriggerGoodJobCron } = await import('./pulsemcp-admin-client/lib/force-trigger-good-job-cron.js');
249
258
  return forceTriggerGoodJobCron(this.apiKey, this.baseUrl, cronKey);
250
259
  }
251
260
  async cleanupGoodJobs(params) {
252
- const { cleanupGoodJobs } = await import('./pulsemcp-admin-client/lib/cleanup-good-jobs.js');
253
261
  return cleanupGoodJobs(this.apiKey, this.baseUrl, params);
254
262
  }
255
263
  // Proctor REST API methods
256
264
  async runExamForMirror(params) {
257
- const { runExamForMirror } = await import('./pulsemcp-admin-client/lib/run-exam-for-mirror.js');
258
265
  return runExamForMirror(this.apiKey, this.baseUrl, params);
259
266
  }
260
267
  async saveResultsForMirror(params) {
261
- const { saveResultsForMirror } = await import('./pulsemcp-admin-client/lib/save-results-for-mirror.js');
262
268
  return saveResultsForMirror(this.apiKey, this.baseUrl, params);
263
269
  }
264
270
  async getProctorRuns(params) {
265
- const { getProctorRuns } = await import('./pulsemcp-admin-client/lib/get-proctor-runs.js');
266
271
  return getProctorRuns(this.apiKey, this.baseUrl, params);
267
272
  }
268
273
  // Discovered URL REST API methods
269
274
  async getDiscoveredUrls(params) {
270
- const { getDiscoveredUrls } = await import('./pulsemcp-admin-client/lib/get-discovered-urls.js');
271
275
  return getDiscoveredUrls(this.apiKey, this.baseUrl, params);
272
276
  }
273
277
  async markDiscoveredUrlProcessed(params) {
274
- const { markDiscoveredUrlProcessed } = await import('./pulsemcp-admin-client/lib/mark-discovered-url-processed.js');
275
278
  return markDiscoveredUrlProcessed(this.apiKey, this.baseUrl, params);
276
279
  }
277
280
  async getDiscoveredUrlStats() {
278
- const { getDiscoveredUrlStats } = await import('./pulsemcp-admin-client/lib/get-discovered-url-stats.js');
279
281
  return getDiscoveredUrlStats(this.apiKey, this.baseUrl);
280
282
  }
281
283
  }
@@ -151,6 +151,12 @@ Use cases:
151
151
  if (run.remotes.length > 0) {
152
152
  content += ` Remotes: ${run.remotes.join(', ')}\n`;
153
153
  }
154
+ if (run.known_missing_init_tools_list) {
155
+ content += ` Known Missing Init Tools List: yes\n`;
156
+ }
157
+ if (run.known_missing_auth_check) {
158
+ content += ` Known Missing Auth Check: yes\n`;
159
+ }
154
160
  content += '\n';
155
161
  }
156
162
  return { content: [{ type: 'text', text: content.trim() }] };
@@ -24,9 +24,9 @@ const PARAM_DESCRIPTIONS = {
24
24
  github_repo: 'GitHub repository name (without owner prefix).',
25
25
  github_subfolder: 'Subfolder path within the repository, for monorepos. Omit for root-level projects.',
26
26
  // Remote endpoints
27
- remote: 'Array of remote endpoint configurations for MCP servers. Each remote can have: id (existing remote ID or blank for new), url_direct, url_setup, transport (e.g., "sse"), host_platform (e.g., "smithery"), host_infrastructure (e.g., "cloudflare"), authentication_method (e.g., "open"), cost (e.g., "free"), status (defaults to "live"), display_name, and internal_notes.',
27
+ remote: 'Array of remote endpoint configurations for MCP servers. Providing this replaces ALL existing remotes. Omitting leaves them unchanged. Pass an empty array to delete all. Each remote can have: id (existing remote ID or blank for new), url_direct, url_setup, transport (e.g., "sse"), host_platform (e.g., "smithery"), host_infrastructure (e.g., "cloudflare"), authentication_method (e.g., "open"), cost (e.g., "free"), status (defaults to "live"), display_name, and internal_notes.',
28
28
  // Canonical URLs
29
- canonical: 'Array of canonical URL configurations. Each entry must have: url (the canonical URL), scope (one of "domain", "subdomain", or "url"), and optional note for additional context.',
29
+ canonical: 'Array of canonical URL configurations. Providing this replaces ALL existing canonical URLs. Omitting leaves them unchanged. Pass an empty array to delete all. Each entry must have: url (the canonical URL), scope (one of "domain", "subdomain", or "url"), and optional note for additional context.',
30
30
  // Flags
31
31
  verified_no_remote_canonicals: 'Mark that this server has been verified to have no remote canonical URLs (true = verified no remote canonicals exist, false = reset/canonicals found)',
32
32
  // Other fields
@@ -106,14 +106,17 @@ export function saveMCPImplementation(_server, clientFactory) {
106
106
  **Creating a new implementation:**
107
107
  - Omit the \`id\` field to create a new implementation
108
108
  - Required fields for creation: \`name\`, \`type\` (either "server" or "client")
109
+ - Remote endpoints and canonical URLs CAN be included on creation
109
110
 
110
111
  **Updating an existing implementation:**
111
112
  - Provide the \`id\` field to update an existing implementation
112
- - Only provided fields will be updated; omitted fields remain unchanged
113
+ - Only provided fields will be updated; **omitted fields remain unchanged**
114
+ - Omitting \`remote\` or \`canonical\` leaves existing values unchanged (does NOT clear them)
115
+ - Providing \`remote: []\` or \`canonical: []\` (empty array) will DELETE all existing entries
113
116
 
114
117
  All business logic from the Rails controller is applied (validation, associations, callbacks).
115
118
 
116
- Example request (CREATE new implementation):
119
+ Example request (CREATE with remote endpoints and canonical URLs):
117
120
  {
118
121
  "name": "My New MCP Server",
119
122
  "type": "server",
@@ -121,7 +124,19 @@ Example request (CREATE new implementation):
121
124
  "classification": "community",
122
125
  "implementation_language": "typescript",
123
126
  "github_owner": "myorg",
124
- "github_repo": "my-mcp-server"
127
+ "github_repo": "my-mcp-server",
128
+ "remote": [
129
+ {
130
+ "url_direct": "https://api.example.com/mcp",
131
+ "transport": "sse",
132
+ "host_platform": "smithery",
133
+ "authentication_method": "open",
134
+ "cost": "free"
135
+ }
136
+ ],
137
+ "canonical": [
138
+ { "url": "https://github.com/myorg/my-mcp-server", "scope": "url" }
139
+ ]
125
140
  }
126
141
 
127
142
  Example request (UPDATE existing implementation):
@@ -134,7 +149,7 @@ Example request (UPDATE existing implementation):
134
149
  "implementation_language": "typescript"
135
150
  }
136
151
 
137
- Example request (with remote endpoints - new remote):
152
+ Example request (UPDATE with remote endpoints - replaces ALL existing remotes):
138
153
  {
139
154
  "id": 11371,
140
155
  "remote": [
@@ -151,21 +166,12 @@ Example request (with remote endpoints - new remote):
151
166
  ]
152
167
  }
153
168
 
154
- Example response:
155
- {
156
- "id": 11371,
157
- "name": "GitHub MCP Server",
158
- "slug": "github-mcp-server",
159
- "type": "server",
160
- "status": "live",
161
- "classification": "official",
162
- "updated_at": "2024-01-20T16:30:00Z"
163
- }
164
-
165
169
  Important notes:
166
170
  - Omit \`id\` to CREATE, provide \`id\` to UPDATE
167
171
  - When creating: \`name\` and \`type\` are required
168
172
  - When updating: only provided fields will be changed
173
+ - **Omission semantics:** omitting \`remote\` or \`canonical\` leaves them unchanged. To clear them, pass an empty array.
174
+ - Providing \`remote\` or \`canonical\` replaces ALL existing entries (not a merge)
169
175
  - CREATE-ONLY restrictions:
170
176
  - \`github_stars\` is read-only (derived from GitHub repository)
171
177
  - \`mcp_server_id\`/\`mcp_client_id\` are created automatically based on \`type\`
@@ -174,17 +180,7 @@ Important notes:
174
180
  - Setting mcp_server_id or mcp_client_id to null will unlink the association (UPDATE only)
175
181
  - Remote endpoints are for MCP servers only and configure how they can be accessed
176
182
  - Canonical URLs help identify the authoritative source for the implementation
177
-
178
- Use cases:
179
- - Create new MCP implementation entries
180
- - Update draft implementations before publishing
181
- - Change implementation status (draft → live, live → archived)
182
- - Update metadata (stars, language, classification)
183
- - Link or unlink MCP server/client associations
184
- - Update descriptions and documentation
185
- - Modify URLs and provider information
186
- - Add or update remote endpoint configurations for servers
187
- - Set canonical URLs for implementations`,
183
+ - After creating/updating, use \`get_mcp_server\` to verify the full state including remotes and canonical URLs`,
188
184
  inputSchema: {
189
185
  type: 'object',
190
186
  properties: {
@@ -377,9 +373,25 @@ Use cases:
377
373
  if (implementation.url) {
378
374
  content += `**URL:** ${implementation.url}\n`;
379
375
  }
376
+ if (implementation.canonical && implementation.canonical.length > 0) {
377
+ content += `**Canonical URLs:** ${implementation.canonical.length}\n`;
378
+ implementation.canonical.forEach((c) => {
379
+ content += ` - ${c.url} (${c.scope})\n`;
380
+ });
381
+ }
382
+ const remotes = implementation.mcp_server?.remotes;
383
+ if (remotes && remotes.length > 0) {
384
+ content += `**Remote Endpoints:** ${remotes.length}\n`;
385
+ remotes.forEach((r) => {
386
+ content += ` - ${r.display_name || r.url_direct || `ID ${r.id}`}\n`;
387
+ });
388
+ }
380
389
  if (implementation.created_at) {
381
390
  content += `**Created:** ${new Date(implementation.created_at).toLocaleDateString()}\n`;
382
391
  }
392
+ if (implementation.type === 'server') {
393
+ content += `\n**Tip:** Use \`get_mcp_server\` with slug \`${implementation.slug}\` to verify the full state including remotes and canonical URLs.\n`;
394
+ }
383
395
  return {
384
396
  content: [
385
397
  {
@@ -434,6 +446,19 @@ Use cases:
434
446
  if (implementation.mcp_client_id) {
435
447
  content += `**Linked MCP Client ID:** ${implementation.mcp_client_id}\n`;
436
448
  }
449
+ if (implementation.canonical && implementation.canonical.length > 0) {
450
+ content += `**Canonical URLs:** ${implementation.canonical.length}\n`;
451
+ implementation.canonical.forEach((c) => {
452
+ content += ` - ${c.url} (${c.scope})\n`;
453
+ });
454
+ }
455
+ const updateRemotes = implementation.mcp_server?.remotes;
456
+ if (updateRemotes && updateRemotes.length > 0) {
457
+ content += `**Remote Endpoints:** ${updateRemotes.length}\n`;
458
+ updateRemotes.forEach((r) => {
459
+ content += ` - ${r.display_name || r.url_direct || `ID ${r.id}`}\n`;
460
+ });
461
+ }
437
462
  if (implementation.updated_at) {
438
463
  content += `**Updated:** ${new Date(implementation.updated_at).toLocaleDateString()}\n`;
439
464
  }
@@ -18,9 +18,9 @@ const PARAM_DESCRIPTIONS = {
18
18
  recommended: 'Mark this server as recommended by PulseMCP',
19
19
  verified_no_remote_canonicals: 'Mark that this server has been verified to have no remote canonical URLs (true = verified no remote canonicals exist, false = reset/canonicals found)',
20
20
  created_on_override: 'Override the automatically derived created date (ISO date string, e.g., "2025-01-15")',
21
- tags: 'Tags for the server. Replaces all existing tags when provided. Use tag slugs.',
22
- canonical_urls: 'Authoritative URLs for the server. Replaces all existing canonical URLs when provided.',
23
- remotes: 'Remote endpoints for the server. Replaces all existing remotes when provided.',
21
+ tags: 'Tags for the server. Providing this replaces ALL existing tags. Omitting leaves them unchanged. Pass an empty array to delete all. Use tag slugs.',
22
+ canonical_urls: 'Authoritative URLs for the server. Providing this replaces ALL existing canonical URLs. Omitting leaves them unchanged. Pass an empty array to delete all.',
23
+ remotes: 'Remote endpoints for the server. Providing this replaces ALL existing remotes. Omitting leaves them unchanged. Pass an empty array to delete all.',
24
24
  internal_notes: 'Admin-only internal notes',
25
25
  };
26
26
  const CanonicalUrlSchema = z.object({
@@ -99,10 +99,15 @@ const UpdateMCPServerSchema = z.object({
99
99
  export function updateMCPServer(_server, clientFactory) {
100
100
  return {
101
101
  name: 'update_mcp_server',
102
- description: `Update an MCP server's information. Only provided fields will be updated.
102
+ description: `Update an MCP server's information. Only provided fields will be updated; **omitted fields remain unchanged**.
103
103
 
104
104
  **Important:** Use the \`implementation_id\` from \`get_mcp_server\` or \`list_mcp_servers\`, NOT the server ID or slug.
105
105
 
106
+ ## Omission semantics
107
+ - **Omitting** \`remotes\`, \`canonical_urls\`, or \`tags\` leaves existing values **unchanged** (does NOT clear them)
108
+ - **Providing** \`remotes\`, \`canonical_urls\`, or \`tags\` **replaces ALL** existing entries (not a merge)
109
+ - To **delete all** entries, pass an empty array (e.g., \`"remotes": []\`)
110
+
106
111
  ## Updating Basic Info
107
112
  \`\`\`json
108
113
  {
@@ -126,7 +131,7 @@ export function updateMCPServer(_server, clientFactory) {
126
131
  \`\`\`
127
132
 
128
133
  ## Adding/Updating Canonical URLs
129
- Providing canonical_urls replaces ALL existing canonical URLs:
134
+ Providing canonical_urls replaces ALL existing canonical URLs (omitting leaves them unchanged):
130
135
  \`\`\`json
131
136
  {
132
137
  "implementation_id": 456,
@@ -138,7 +143,7 @@ Providing canonical_urls replaces ALL existing canonical URLs:
138
143
  \`\`\`
139
144
 
140
145
  ## Adding/Updating Remote Endpoints
141
- Providing remotes replaces ALL existing remote endpoints:
146
+ Providing remotes replaces ALL existing remote endpoints (omitting leaves them unchanged):
142
147
  \`\`\`json
143
148
  {
144
149
  "implementation_id": 456,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "pulsemcp-cms-admin-mcp-server",
3
- "version": "0.9.2",
3
+ "version": "0.9.6",
4
4
  "description": "Local implementation of PulseMCP CMS Admin MCP server",
5
5
  "mcpName": "com.pulsemcp.servers/pulsemcp-cms-admin",
6
6
  "main": "build/index.js",
@@ -56,6 +56,8 @@ export async function getProctorRuns(apiKey, baseUrl, params) {
56
56
  num_tools: run.num_tools,
57
57
  packages: run.packages,
58
58
  remotes: run.remotes,
59
+ known_missing_init_tools_list: run.known_missing_init_tools_list || false,
60
+ known_missing_auth_check: run.known_missing_auth_check || false,
59
61
  })),
60
62
  pagination: {
61
63
  current_page: data.meta.current_page,
package/shared/server.js CHANGED
@@ -1,5 +1,72 @@
1
1
  import { Server } from '@modelcontextprotocol/sdk/server/index.js';
2
2
  import { createRegisterTools } from './tools.js';
3
+ // Static imports for all API client functions (replaces dynamic imports
4
+ // which can fail at runtime in some environments due to ESM resolution)
5
+ import { getPosts } from './pulsemcp-admin-client/lib/get-posts.js';
6
+ import { getPost } from './pulsemcp-admin-client/lib/get-post.js';
7
+ import { createPost } from './pulsemcp-admin-client/lib/create-post.js';
8
+ import { updatePost } from './pulsemcp-admin-client/lib/update-post.js';
9
+ import { uploadImage } from './pulsemcp-admin-client/lib/upload-image.js';
10
+ import { getAuthors } from './pulsemcp-admin-client/lib/get-authors.js';
11
+ import { getAuthorBySlug } from './pulsemcp-admin-client/lib/get-author-by-slug.js';
12
+ import { getAuthorById } from './pulsemcp-admin-client/lib/get-author-by-id.js';
13
+ import { getMCPServerBySlug } from './pulsemcp-admin-client/lib/get-mcp-server-by-slug.js';
14
+ import { getMCPServerById } from './pulsemcp-admin-client/lib/get-mcp-server-by-id.js';
15
+ import { getMCPClientBySlug } from './pulsemcp-admin-client/lib/get-mcp-client-by-slug.js';
16
+ import { getMCPClientById } from './pulsemcp-admin-client/lib/get-mcp-client-by-id.js';
17
+ import { getMCPImplementationById } from './pulsemcp-admin-client/lib/get-mcp-implementation-by-id.js';
18
+ import { searchMCPImplementations } from './pulsemcp-admin-client/lib/search-mcp-implementations.js';
19
+ import { getDraftMCPImplementations } from './pulsemcp-admin-client/lib/get-draft-mcp-implementations.js';
20
+ import { saveMCPImplementation } from './pulsemcp-admin-client/lib/save-mcp-implementation.js';
21
+ import { createMCPImplementation } from './pulsemcp-admin-client/lib/create-mcp-implementation.js';
22
+ import { sendEmail } from './pulsemcp-admin-client/lib/send-email.js';
23
+ import { searchProviders } from './pulsemcp-admin-client/lib/search-providers.js';
24
+ import { getProviderById } from './pulsemcp-admin-client/lib/get-provider-by-id.js';
25
+ import { getOfficialMirrorQueueItems } from './pulsemcp-admin-client/lib/get-official-mirror-queue-items.js';
26
+ import { getOfficialMirrorQueueItem } from './pulsemcp-admin-client/lib/get-official-mirror-queue-item.js';
27
+ import { approveOfficialMirrorQueueItem } from './pulsemcp-admin-client/lib/approve-official-mirror-queue-item.js';
28
+ import { approveOfficialMirrorQueueItemWithoutModifying } from './pulsemcp-admin-client/lib/approve-official-mirror-queue-item-without-modifying.js';
29
+ import { rejectOfficialMirrorQueueItem } from './pulsemcp-admin-client/lib/reject-official-mirror-queue-item.js';
30
+ import { addOfficialMirrorToRegularQueue } from './pulsemcp-admin-client/lib/add-official-mirror-to-regular-queue.js';
31
+ import { unlinkOfficialMirrorQueueItem } from './pulsemcp-admin-client/lib/unlink-official-mirror-queue-item.js';
32
+ import { getUnofficialMirrors } from './pulsemcp-admin-client/lib/get-unofficial-mirrors.js';
33
+ import { getUnofficialMirror } from './pulsemcp-admin-client/lib/get-unofficial-mirror.js';
34
+ import { createUnofficialMirror } from './pulsemcp-admin-client/lib/create-unofficial-mirror.js';
35
+ import { updateUnofficialMirror } from './pulsemcp-admin-client/lib/update-unofficial-mirror.js';
36
+ import { deleteUnofficialMirror } from './pulsemcp-admin-client/lib/delete-unofficial-mirror.js';
37
+ import { getOfficialMirrors } from './pulsemcp-admin-client/lib/get-official-mirrors.js';
38
+ import { getOfficialMirror } from './pulsemcp-admin-client/lib/get-official-mirror.js';
39
+ import { getTenants } from './pulsemcp-admin-client/lib/get-tenants.js';
40
+ import { getTenant } from './pulsemcp-admin-client/lib/get-tenant.js';
41
+ import { getMcpJsons } from './pulsemcp-admin-client/lib/get-mcp-jsons.js';
42
+ import { getMcpJson } from './pulsemcp-admin-client/lib/get-mcp-json.js';
43
+ import { createMcpJson } from './pulsemcp-admin-client/lib/create-mcp-json.js';
44
+ import { updateMcpJson } from './pulsemcp-admin-client/lib/update-mcp-json.js';
45
+ import { deleteMcpJson } from './pulsemcp-admin-client/lib/delete-mcp-json.js';
46
+ import { getUnifiedMCPServers } from './pulsemcp-admin-client/lib/get-unified-mcp-servers.js';
47
+ import { getUnifiedMCPServer } from './pulsemcp-admin-client/lib/get-unified-mcp-server.js';
48
+ import { updateUnifiedMCPServer } from './pulsemcp-admin-client/lib/update-unified-mcp-server.js';
49
+ import { getRedirects } from './pulsemcp-admin-client/lib/get-redirects.js';
50
+ import { getRedirect } from './pulsemcp-admin-client/lib/get-redirect.js';
51
+ import { createRedirect } from './pulsemcp-admin-client/lib/create-redirect.js';
52
+ import { updateRedirect } from './pulsemcp-admin-client/lib/update-redirect.js';
53
+ import { deleteRedirect } from './pulsemcp-admin-client/lib/delete-redirect.js';
54
+ import { getGoodJobs } from './pulsemcp-admin-client/lib/get-good-jobs.js';
55
+ import { getGoodJob } from './pulsemcp-admin-client/lib/get-good-job.js';
56
+ import { getGoodJobCronSchedules } from './pulsemcp-admin-client/lib/get-good-job-cron-schedules.js';
57
+ import { getGoodJobProcesses } from './pulsemcp-admin-client/lib/get-good-job-processes.js';
58
+ import { getGoodJobStatistics } from './pulsemcp-admin-client/lib/get-good-job-statistics.js';
59
+ import { retryGoodJob } from './pulsemcp-admin-client/lib/retry-good-job.js';
60
+ import { discardGoodJob } from './pulsemcp-admin-client/lib/discard-good-job.js';
61
+ import { rescheduleGoodJob } from './pulsemcp-admin-client/lib/reschedule-good-job.js';
62
+ import { forceTriggerGoodJobCron } from './pulsemcp-admin-client/lib/force-trigger-good-job-cron.js';
63
+ import { cleanupGoodJobs } from './pulsemcp-admin-client/lib/cleanup-good-jobs.js';
64
+ import { runExamForMirror } from './pulsemcp-admin-client/lib/run-exam-for-mirror.js';
65
+ import { saveResultsForMirror } from './pulsemcp-admin-client/lib/save-results-for-mirror.js';
66
+ import { getProctorRuns } from './pulsemcp-admin-client/lib/get-proctor-runs.js';
67
+ import { getDiscoveredUrls } from './pulsemcp-admin-client/lib/get-discovered-urls.js';
68
+ import { markDiscoveredUrlProcessed } from './pulsemcp-admin-client/lib/mark-discovered-url-processed.js';
69
+ import { getDiscoveredUrlStats } from './pulsemcp-admin-client/lib/get-discovered-url-stats.js';
3
70
  // PulseMCP Admin API client implementation
4
71
  export class PulseMCPAdminClient {
5
72
  apiKey;
@@ -9,273 +76,208 @@ export class PulseMCPAdminClient {
9
76
  this.baseUrl = baseUrl || 'https://admin.pulsemcp.com';
10
77
  }
11
78
  async getPosts(params) {
12
- const { getPosts } = await import('./pulsemcp-admin-client/lib/get-posts.js');
13
79
  return getPosts(this.apiKey, this.baseUrl, params);
14
80
  }
15
81
  async getPost(slug) {
16
- const { getPost } = await import('./pulsemcp-admin-client/lib/get-post.js');
17
82
  return getPost(this.apiKey, this.baseUrl, slug);
18
83
  }
19
84
  async createPost(params) {
20
- const { createPost } = await import('./pulsemcp-admin-client/lib/create-post.js');
21
85
  return createPost(this.apiKey, this.baseUrl, params);
22
86
  }
23
87
  async updatePost(slug, params) {
24
- const { updatePost } = await import('./pulsemcp-admin-client/lib/update-post.js');
25
88
  return updatePost(this.apiKey, this.baseUrl, slug, params);
26
89
  }
27
90
  async uploadImage(postSlug, fileName, fileData) {
28
- const { uploadImage } = await import('./pulsemcp-admin-client/lib/upload-image.js');
29
91
  return uploadImage(this.apiKey, this.baseUrl, postSlug, fileName, fileData);
30
92
  }
31
93
  async getAuthors(params) {
32
- const { getAuthors } = await import('./pulsemcp-admin-client/lib/get-authors.js');
33
94
  return getAuthors(this.apiKey, this.baseUrl, params);
34
95
  }
35
96
  async getAuthorBySlug(slug) {
36
- const { getAuthorBySlug } = await import('./pulsemcp-admin-client/lib/get-author-by-slug.js');
37
97
  return getAuthorBySlug(this.apiKey, this.baseUrl, slug);
38
98
  }
39
99
  async getAuthorById(id) {
40
- const { getAuthorById } = await import('./pulsemcp-admin-client/lib/get-author-by-id.js');
41
100
  return getAuthorById(this.apiKey, this.baseUrl, id);
42
101
  }
43
102
  async getMCPServerBySlug(slug) {
44
- const { getMCPServerBySlug } = await import('./pulsemcp-admin-client/lib/get-mcp-server-by-slug.js');
45
103
  return getMCPServerBySlug(this.apiKey, this.baseUrl, slug);
46
104
  }
47
105
  async getMCPServerById(id) {
48
- const { getMCPServerById } = await import('./pulsemcp-admin-client/lib/get-mcp-server-by-id.js');
49
106
  return getMCPServerById(this.apiKey, this.baseUrl, id);
50
107
  }
51
108
  async getMCPClientBySlug(slug) {
52
- const { getMCPClientBySlug } = await import('./pulsemcp-admin-client/lib/get-mcp-client-by-slug.js');
53
109
  return getMCPClientBySlug(this.apiKey, this.baseUrl, slug);
54
110
  }
55
111
  async getMCPClientById(id) {
56
- const { getMCPClientById } = await import('./pulsemcp-admin-client/lib/get-mcp-client-by-id.js');
57
112
  return getMCPClientById(this.apiKey, this.baseUrl, id);
58
113
  }
59
114
  async getMCPImplementationById(id) {
60
- const { getMCPImplementationById } = await import('./pulsemcp-admin-client/lib/get-mcp-implementation-by-id.js');
61
115
  return getMCPImplementationById(this.apiKey, this.baseUrl, id);
62
116
  }
63
117
  async searchMCPImplementations(params) {
64
- const { searchMCPImplementations } = await import('./pulsemcp-admin-client/lib/search-mcp-implementations.js');
65
118
  return searchMCPImplementations(this.apiKey, this.baseUrl, params);
66
119
  }
67
120
  async getDraftMCPImplementations(params) {
68
- const { getDraftMCPImplementations } = await import('./pulsemcp-admin-client/lib/get-draft-mcp-implementations.js');
69
121
  return getDraftMCPImplementations(this.apiKey, this.baseUrl, params);
70
122
  }
71
123
  async saveMCPImplementation(id, params) {
72
- const { saveMCPImplementation } = await import('./pulsemcp-admin-client/lib/save-mcp-implementation.js');
73
124
  return saveMCPImplementation(this.apiKey, this.baseUrl, id, params);
74
125
  }
75
126
  async createMCPImplementation(params) {
76
- const { createMCPImplementation } = await import('./pulsemcp-admin-client/lib/create-mcp-implementation.js');
77
127
  return createMCPImplementation(this.apiKey, this.baseUrl, params);
78
128
  }
79
129
  async sendEmail(params) {
80
- const { sendEmail } = await import('./pulsemcp-admin-client/lib/send-email.js');
81
130
  return sendEmail(this.apiKey, this.baseUrl, params);
82
131
  }
83
132
  async searchProviders(params) {
84
- const { searchProviders } = await import('./pulsemcp-admin-client/lib/search-providers.js');
85
133
  return searchProviders(this.apiKey, this.baseUrl, params);
86
134
  }
87
135
  async getProviderById(id) {
88
- const { getProviderById } = await import('./pulsemcp-admin-client/lib/get-provider-by-id.js');
89
136
  return getProviderById(this.apiKey, this.baseUrl, id);
90
137
  }
91
138
  // Official Mirror Queue methods
92
139
  async getOfficialMirrorQueueItems(params) {
93
- const { getOfficialMirrorQueueItems } = await import('./pulsemcp-admin-client/lib/get-official-mirror-queue-items.js');
94
140
  return getOfficialMirrorQueueItems(this.apiKey, this.baseUrl, params);
95
141
  }
96
142
  async getOfficialMirrorQueueItem(id) {
97
- const { getOfficialMirrorQueueItem } = await import('./pulsemcp-admin-client/lib/get-official-mirror-queue-item.js');
98
143
  return getOfficialMirrorQueueItem(this.apiKey, this.baseUrl, id);
99
144
  }
100
145
  async approveOfficialMirrorQueueItem(id, mcpServerSlug) {
101
- const { approveOfficialMirrorQueueItem } = await import('./pulsemcp-admin-client/lib/approve-official-mirror-queue-item.js');
102
146
  return approveOfficialMirrorQueueItem(this.apiKey, this.baseUrl, id, mcpServerSlug);
103
147
  }
104
148
  async approveOfficialMirrorQueueItemWithoutModifying(id) {
105
- const { approveOfficialMirrorQueueItemWithoutModifying } = await import('./pulsemcp-admin-client/lib/approve-official-mirror-queue-item-without-modifying.js');
106
149
  return approveOfficialMirrorQueueItemWithoutModifying(this.apiKey, this.baseUrl, id);
107
150
  }
108
151
  async rejectOfficialMirrorQueueItem(id) {
109
- const { rejectOfficialMirrorQueueItem } = await import('./pulsemcp-admin-client/lib/reject-official-mirror-queue-item.js');
110
152
  return rejectOfficialMirrorQueueItem(this.apiKey, this.baseUrl, id);
111
153
  }
112
154
  async addOfficialMirrorToRegularQueue(id) {
113
- const { addOfficialMirrorToRegularQueue } = await import('./pulsemcp-admin-client/lib/add-official-mirror-to-regular-queue.js');
114
155
  return addOfficialMirrorToRegularQueue(this.apiKey, this.baseUrl, id);
115
156
  }
116
157
  async unlinkOfficialMirrorQueueItem(id) {
117
- const { unlinkOfficialMirrorQueueItem } = await import('./pulsemcp-admin-client/lib/unlink-official-mirror-queue-item.js');
118
158
  return unlinkOfficialMirrorQueueItem(this.apiKey, this.baseUrl, id);
119
159
  }
120
160
  // Unofficial Mirror REST API methods
121
161
  async getUnofficialMirrors(params) {
122
- const { getUnofficialMirrors } = await import('./pulsemcp-admin-client/lib/get-unofficial-mirrors.js');
123
162
  return getUnofficialMirrors(this.apiKey, this.baseUrl, params);
124
163
  }
125
164
  async getUnofficialMirror(id) {
126
- const { getUnofficialMirror } = await import('./pulsemcp-admin-client/lib/get-unofficial-mirror.js');
127
165
  return getUnofficialMirror(this.apiKey, this.baseUrl, id);
128
166
  }
129
167
  async createUnofficialMirror(params) {
130
- const { createUnofficialMirror } = await import('./pulsemcp-admin-client/lib/create-unofficial-mirror.js');
131
168
  return createUnofficialMirror(this.apiKey, this.baseUrl, params);
132
169
  }
133
170
  async updateUnofficialMirror(id, params) {
134
- const { updateUnofficialMirror } = await import('./pulsemcp-admin-client/lib/update-unofficial-mirror.js');
135
171
  return updateUnofficialMirror(this.apiKey, this.baseUrl, id, params);
136
172
  }
137
173
  async deleteUnofficialMirror(id) {
138
- const { deleteUnofficialMirror } = await import('./pulsemcp-admin-client/lib/delete-unofficial-mirror.js');
139
174
  return deleteUnofficialMirror(this.apiKey, this.baseUrl, id);
140
175
  }
141
176
  // Official Mirror REST API methods (read-only)
142
177
  async getOfficialMirrors(params) {
143
- const { getOfficialMirrors } = await import('./pulsemcp-admin-client/lib/get-official-mirrors.js');
144
178
  return getOfficialMirrors(this.apiKey, this.baseUrl, params);
145
179
  }
146
180
  async getOfficialMirror(id) {
147
- const { getOfficialMirror } = await import('./pulsemcp-admin-client/lib/get-official-mirror.js');
148
181
  return getOfficialMirror(this.apiKey, this.baseUrl, id);
149
182
  }
150
183
  // Tenant REST API methods (read-only)
151
184
  async getTenants(params) {
152
- const { getTenants } = await import('./pulsemcp-admin-client/lib/get-tenants.js');
153
185
  return getTenants(this.apiKey, this.baseUrl, params);
154
186
  }
155
187
  async getTenant(idOrSlug) {
156
- const { getTenant } = await import('./pulsemcp-admin-client/lib/get-tenant.js');
157
188
  return getTenant(this.apiKey, this.baseUrl, idOrSlug);
158
189
  }
159
190
  // MCP JSON REST API methods
160
191
  async getMcpJsons(params) {
161
- const { getMcpJsons } = await import('./pulsemcp-admin-client/lib/get-mcp-jsons.js');
162
192
  return getMcpJsons(this.apiKey, this.baseUrl, params);
163
193
  }
164
194
  async getMcpJson(id) {
165
- const { getMcpJson } = await import('./pulsemcp-admin-client/lib/get-mcp-json.js');
166
195
  return getMcpJson(this.apiKey, this.baseUrl, id);
167
196
  }
168
197
  async createMcpJson(params) {
169
- const { createMcpJson } = await import('./pulsemcp-admin-client/lib/create-mcp-json.js');
170
198
  return createMcpJson(this.apiKey, this.baseUrl, params);
171
199
  }
172
200
  async updateMcpJson(id, params) {
173
- const { updateMcpJson } = await import('./pulsemcp-admin-client/lib/update-mcp-json.js');
174
201
  return updateMcpJson(this.apiKey, this.baseUrl, id, params);
175
202
  }
176
203
  async deleteMcpJson(id) {
177
- const { deleteMcpJson } = await import('./pulsemcp-admin-client/lib/delete-mcp-json.js');
178
204
  return deleteMcpJson(this.apiKey, this.baseUrl, id);
179
205
  }
180
206
  // Unified MCP Server methods (abstracted interface)
181
207
  async getUnifiedMCPServers(params) {
182
- const { getUnifiedMCPServers } = await import('./pulsemcp-admin-client/lib/get-unified-mcp-servers.js');
183
208
  return getUnifiedMCPServers(this.apiKey, this.baseUrl, params);
184
209
  }
185
210
  async getUnifiedMCPServer(slug) {
186
- const { getUnifiedMCPServer } = await import('./pulsemcp-admin-client/lib/get-unified-mcp-server.js');
187
211
  return getUnifiedMCPServer(this.apiKey, this.baseUrl, slug);
188
212
  }
189
213
  async updateUnifiedMCPServer(implementationId, params) {
190
- const { updateUnifiedMCPServer } = await import('./pulsemcp-admin-client/lib/update-unified-mcp-server.js');
191
214
  return updateUnifiedMCPServer(this.apiKey, this.baseUrl, implementationId, params);
192
215
  }
193
216
  // Redirect REST API methods
194
217
  async getRedirects(params) {
195
- const { getRedirects } = await import('./pulsemcp-admin-client/lib/get-redirects.js');
196
218
  return getRedirects(this.apiKey, this.baseUrl, params);
197
219
  }
198
220
  async getRedirect(id) {
199
- const { getRedirect } = await import('./pulsemcp-admin-client/lib/get-redirect.js');
200
221
  return getRedirect(this.apiKey, this.baseUrl, id);
201
222
  }
202
223
  async createRedirect(params) {
203
- const { createRedirect } = await import('./pulsemcp-admin-client/lib/create-redirect.js');
204
224
  return createRedirect(this.apiKey, this.baseUrl, params);
205
225
  }
206
226
  async updateRedirect(id, params) {
207
- const { updateRedirect } = await import('./pulsemcp-admin-client/lib/update-redirect.js');
208
227
  return updateRedirect(this.apiKey, this.baseUrl, id, params);
209
228
  }
210
229
  async deleteRedirect(id) {
211
- const { deleteRedirect } = await import('./pulsemcp-admin-client/lib/delete-redirect.js');
212
230
  return deleteRedirect(this.apiKey, this.baseUrl, id);
213
231
  }
214
232
  // GoodJob REST API methods
215
233
  async getGoodJobs(params) {
216
- const { getGoodJobs } = await import('./pulsemcp-admin-client/lib/get-good-jobs.js');
217
234
  return getGoodJobs(this.apiKey, this.baseUrl, params);
218
235
  }
219
236
  async getGoodJob(id) {
220
- const { getGoodJob } = await import('./pulsemcp-admin-client/lib/get-good-job.js');
221
237
  return getGoodJob(this.apiKey, this.baseUrl, id);
222
238
  }
223
239
  async getGoodJobCronSchedules() {
224
- const { getGoodJobCronSchedules } = await import('./pulsemcp-admin-client/lib/get-good-job-cron-schedules.js');
225
240
  return getGoodJobCronSchedules(this.apiKey, this.baseUrl);
226
241
  }
227
242
  async getGoodJobProcesses() {
228
- const { getGoodJobProcesses } = await import('./pulsemcp-admin-client/lib/get-good-job-processes.js');
229
243
  return getGoodJobProcesses(this.apiKey, this.baseUrl);
230
244
  }
231
245
  async getGoodJobStatistics() {
232
- const { getGoodJobStatistics } = await import('./pulsemcp-admin-client/lib/get-good-job-statistics.js');
233
246
  return getGoodJobStatistics(this.apiKey, this.baseUrl);
234
247
  }
235
248
  async retryGoodJob(id) {
236
- const { retryGoodJob } = await import('./pulsemcp-admin-client/lib/retry-good-job.js');
237
249
  return retryGoodJob(this.apiKey, this.baseUrl, id);
238
250
  }
239
251
  async discardGoodJob(id) {
240
- const { discardGoodJob } = await import('./pulsemcp-admin-client/lib/discard-good-job.js');
241
252
  return discardGoodJob(this.apiKey, this.baseUrl, id);
242
253
  }
243
254
  async rescheduleGoodJob(id, scheduledAt) {
244
- const { rescheduleGoodJob } = await import('./pulsemcp-admin-client/lib/reschedule-good-job.js');
245
255
  return rescheduleGoodJob(this.apiKey, this.baseUrl, id, scheduledAt);
246
256
  }
247
257
  async forceTriggerGoodJobCron(cronKey) {
248
- const { forceTriggerGoodJobCron } = await import('./pulsemcp-admin-client/lib/force-trigger-good-job-cron.js');
249
258
  return forceTriggerGoodJobCron(this.apiKey, this.baseUrl, cronKey);
250
259
  }
251
260
  async cleanupGoodJobs(params) {
252
- const { cleanupGoodJobs } = await import('./pulsemcp-admin-client/lib/cleanup-good-jobs.js');
253
261
  return cleanupGoodJobs(this.apiKey, this.baseUrl, params);
254
262
  }
255
263
  // Proctor REST API methods
256
264
  async runExamForMirror(params) {
257
- const { runExamForMirror } = await import('./pulsemcp-admin-client/lib/run-exam-for-mirror.js');
258
265
  return runExamForMirror(this.apiKey, this.baseUrl, params);
259
266
  }
260
267
  async saveResultsForMirror(params) {
261
- const { saveResultsForMirror } = await import('./pulsemcp-admin-client/lib/save-results-for-mirror.js');
262
268
  return saveResultsForMirror(this.apiKey, this.baseUrl, params);
263
269
  }
264
270
  async getProctorRuns(params) {
265
- const { getProctorRuns } = await import('./pulsemcp-admin-client/lib/get-proctor-runs.js');
266
271
  return getProctorRuns(this.apiKey, this.baseUrl, params);
267
272
  }
268
273
  // Discovered URL REST API methods
269
274
  async getDiscoveredUrls(params) {
270
- const { getDiscoveredUrls } = await import('./pulsemcp-admin-client/lib/get-discovered-urls.js');
271
275
  return getDiscoveredUrls(this.apiKey, this.baseUrl, params);
272
276
  }
273
277
  async markDiscoveredUrlProcessed(params) {
274
- const { markDiscoveredUrlProcessed } = await import('./pulsemcp-admin-client/lib/mark-discovered-url-processed.js');
275
278
  return markDiscoveredUrlProcessed(this.apiKey, this.baseUrl, params);
276
279
  }
277
280
  async getDiscoveredUrlStats() {
278
- const { getDiscoveredUrlStats } = await import('./pulsemcp-admin-client/lib/get-discovered-url-stats.js');
279
281
  return getDiscoveredUrlStats(this.apiKey, this.baseUrl);
280
282
  }
281
283
  }
@@ -151,6 +151,12 @@ Use cases:
151
151
  if (run.remotes.length > 0) {
152
152
  content += ` Remotes: ${run.remotes.join(', ')}\n`;
153
153
  }
154
+ if (run.known_missing_init_tools_list) {
155
+ content += ` Known Missing Init Tools List: yes\n`;
156
+ }
157
+ if (run.known_missing_auth_check) {
158
+ content += ` Known Missing Auth Check: yes\n`;
159
+ }
154
160
  content += '\n';
155
161
  }
156
162
  return { content: [{ type: 'text', text: content.trim() }] };
@@ -129,7 +129,7 @@ export declare function saveMCPImplementation(_server: Server, clientFactory: Cl
129
129
  };
130
130
  };
131
131
  };
132
- description: "Array of remote endpoint configurations for MCP servers. Each remote can have: id (existing remote ID or blank for new), url_direct, url_setup, transport (e.g., \"sse\"), host_platform (e.g., \"smithery\"), host_infrastructure (e.g., \"cloudflare\"), authentication_method (e.g., \"open\"), cost (e.g., \"free\"), status (defaults to \"live\"), display_name, and internal_notes.";
132
+ description: "Array of remote endpoint configurations for MCP servers. Providing this replaces ALL existing remotes. Omitting leaves them unchanged. Pass an empty array to delete all. Each remote can have: id (existing remote ID or blank for new), url_direct, url_setup, transport (e.g., \"sse\"), host_platform (e.g., \"smithery\"), host_infrastructure (e.g., \"cloudflare\"), authentication_method (e.g., \"open\"), cost (e.g., \"free\"), status (defaults to \"live\"), display_name, and internal_notes.";
133
133
  };
134
134
  canonical: {
135
135
  type: string;
@@ -149,7 +149,7 @@ export declare function saveMCPImplementation(_server: Server, clientFactory: Cl
149
149
  };
150
150
  required: string[];
151
151
  };
152
- description: "Array of canonical URL configurations. Each entry must have: url (the canonical URL), scope (one of \"domain\", \"subdomain\", or \"url\"), and optional note for additional context.";
152
+ description: "Array of canonical URL configurations. Providing this replaces ALL existing canonical URLs. Omitting leaves them unchanged. Pass an empty array to delete all. Each entry must have: url (the canonical URL), scope (one of \"domain\", \"subdomain\", or \"url\"), and optional note for additional context.";
153
153
  };
154
154
  verified_no_remote_canonicals: {
155
155
  type: string;
@@ -24,9 +24,9 @@ const PARAM_DESCRIPTIONS = {
24
24
  github_repo: 'GitHub repository name (without owner prefix).',
25
25
  github_subfolder: 'Subfolder path within the repository, for monorepos. Omit for root-level projects.',
26
26
  // Remote endpoints
27
- remote: 'Array of remote endpoint configurations for MCP servers. Each remote can have: id (existing remote ID or blank for new), url_direct, url_setup, transport (e.g., "sse"), host_platform (e.g., "smithery"), host_infrastructure (e.g., "cloudflare"), authentication_method (e.g., "open"), cost (e.g., "free"), status (defaults to "live"), display_name, and internal_notes.',
27
+ remote: 'Array of remote endpoint configurations for MCP servers. Providing this replaces ALL existing remotes. Omitting leaves them unchanged. Pass an empty array to delete all. Each remote can have: id (existing remote ID or blank for new), url_direct, url_setup, transport (e.g., "sse"), host_platform (e.g., "smithery"), host_infrastructure (e.g., "cloudflare"), authentication_method (e.g., "open"), cost (e.g., "free"), status (defaults to "live"), display_name, and internal_notes.',
28
28
  // Canonical URLs
29
- canonical: 'Array of canonical URL configurations. Each entry must have: url (the canonical URL), scope (one of "domain", "subdomain", or "url"), and optional note for additional context.',
29
+ canonical: 'Array of canonical URL configurations. Providing this replaces ALL existing canonical URLs. Omitting leaves them unchanged. Pass an empty array to delete all. Each entry must have: url (the canonical URL), scope (one of "domain", "subdomain", or "url"), and optional note for additional context.',
30
30
  // Flags
31
31
  verified_no_remote_canonicals: 'Mark that this server has been verified to have no remote canonical URLs (true = verified no remote canonicals exist, false = reset/canonicals found)',
32
32
  // Other fields
@@ -106,14 +106,17 @@ export function saveMCPImplementation(_server, clientFactory) {
106
106
  **Creating a new implementation:**
107
107
  - Omit the \`id\` field to create a new implementation
108
108
  - Required fields for creation: \`name\`, \`type\` (either "server" or "client")
109
+ - Remote endpoints and canonical URLs CAN be included on creation
109
110
 
110
111
  **Updating an existing implementation:**
111
112
  - Provide the \`id\` field to update an existing implementation
112
- - Only provided fields will be updated; omitted fields remain unchanged
113
+ - Only provided fields will be updated; **omitted fields remain unchanged**
114
+ - Omitting \`remote\` or \`canonical\` leaves existing values unchanged (does NOT clear them)
115
+ - Providing \`remote: []\` or \`canonical: []\` (empty array) will DELETE all existing entries
113
116
 
114
117
  All business logic from the Rails controller is applied (validation, associations, callbacks).
115
118
 
116
- Example request (CREATE new implementation):
119
+ Example request (CREATE with remote endpoints and canonical URLs):
117
120
  {
118
121
  "name": "My New MCP Server",
119
122
  "type": "server",
@@ -121,7 +124,19 @@ Example request (CREATE new implementation):
121
124
  "classification": "community",
122
125
  "implementation_language": "typescript",
123
126
  "github_owner": "myorg",
124
- "github_repo": "my-mcp-server"
127
+ "github_repo": "my-mcp-server",
128
+ "remote": [
129
+ {
130
+ "url_direct": "https://api.example.com/mcp",
131
+ "transport": "sse",
132
+ "host_platform": "smithery",
133
+ "authentication_method": "open",
134
+ "cost": "free"
135
+ }
136
+ ],
137
+ "canonical": [
138
+ { "url": "https://github.com/myorg/my-mcp-server", "scope": "url" }
139
+ ]
125
140
  }
126
141
 
127
142
  Example request (UPDATE existing implementation):
@@ -134,7 +149,7 @@ Example request (UPDATE existing implementation):
134
149
  "implementation_language": "typescript"
135
150
  }
136
151
 
137
- Example request (with remote endpoints - new remote):
152
+ Example request (UPDATE with remote endpoints - replaces ALL existing remotes):
138
153
  {
139
154
  "id": 11371,
140
155
  "remote": [
@@ -151,21 +166,12 @@ Example request (with remote endpoints - new remote):
151
166
  ]
152
167
  }
153
168
 
154
- Example response:
155
- {
156
- "id": 11371,
157
- "name": "GitHub MCP Server",
158
- "slug": "github-mcp-server",
159
- "type": "server",
160
- "status": "live",
161
- "classification": "official",
162
- "updated_at": "2024-01-20T16:30:00Z"
163
- }
164
-
165
169
  Important notes:
166
170
  - Omit \`id\` to CREATE, provide \`id\` to UPDATE
167
171
  - When creating: \`name\` and \`type\` are required
168
172
  - When updating: only provided fields will be changed
173
+ - **Omission semantics:** omitting \`remote\` or \`canonical\` leaves them unchanged. To clear them, pass an empty array.
174
+ - Providing \`remote\` or \`canonical\` replaces ALL existing entries (not a merge)
169
175
  - CREATE-ONLY restrictions:
170
176
  - \`github_stars\` is read-only (derived from GitHub repository)
171
177
  - \`mcp_server_id\`/\`mcp_client_id\` are created automatically based on \`type\`
@@ -174,17 +180,7 @@ Important notes:
174
180
  - Setting mcp_server_id or mcp_client_id to null will unlink the association (UPDATE only)
175
181
  - Remote endpoints are for MCP servers only and configure how they can be accessed
176
182
  - Canonical URLs help identify the authoritative source for the implementation
177
-
178
- Use cases:
179
- - Create new MCP implementation entries
180
- - Update draft implementations before publishing
181
- - Change implementation status (draft → live, live → archived)
182
- - Update metadata (stars, language, classification)
183
- - Link or unlink MCP server/client associations
184
- - Update descriptions and documentation
185
- - Modify URLs and provider information
186
- - Add or update remote endpoint configurations for servers
187
- - Set canonical URLs for implementations`,
183
+ - After creating/updating, use \`get_mcp_server\` to verify the full state including remotes and canonical URLs`,
188
184
  inputSchema: {
189
185
  type: 'object',
190
186
  properties: {
@@ -377,9 +373,25 @@ Use cases:
377
373
  if (implementation.url) {
378
374
  content += `**URL:** ${implementation.url}\n`;
379
375
  }
376
+ if (implementation.canonical && implementation.canonical.length > 0) {
377
+ content += `**Canonical URLs:** ${implementation.canonical.length}\n`;
378
+ implementation.canonical.forEach((c) => {
379
+ content += ` - ${c.url} (${c.scope})\n`;
380
+ });
381
+ }
382
+ const remotes = implementation.mcp_server?.remotes;
383
+ if (remotes && remotes.length > 0) {
384
+ content += `**Remote Endpoints:** ${remotes.length}\n`;
385
+ remotes.forEach((r) => {
386
+ content += ` - ${r.display_name || r.url_direct || `ID ${r.id}`}\n`;
387
+ });
388
+ }
380
389
  if (implementation.created_at) {
381
390
  content += `**Created:** ${new Date(implementation.created_at).toLocaleDateString()}\n`;
382
391
  }
392
+ if (implementation.type === 'server') {
393
+ content += `\n**Tip:** Use \`get_mcp_server\` with slug \`${implementation.slug}\` to verify the full state including remotes and canonical URLs.\n`;
394
+ }
383
395
  return {
384
396
  content: [
385
397
  {
@@ -434,6 +446,19 @@ Use cases:
434
446
  if (implementation.mcp_client_id) {
435
447
  content += `**Linked MCP Client ID:** ${implementation.mcp_client_id}\n`;
436
448
  }
449
+ if (implementation.canonical && implementation.canonical.length > 0) {
450
+ content += `**Canonical URLs:** ${implementation.canonical.length}\n`;
451
+ implementation.canonical.forEach((c) => {
452
+ content += ` - ${c.url} (${c.scope})\n`;
453
+ });
454
+ }
455
+ const updateRemotes = implementation.mcp_server?.remotes;
456
+ if (updateRemotes && updateRemotes.length > 0) {
457
+ content += `**Remote Endpoints:** ${updateRemotes.length}\n`;
458
+ updateRemotes.forEach((r) => {
459
+ content += ` - ${r.display_name || r.url_direct || `ID ${r.id}`}\n`;
460
+ });
461
+ }
437
462
  if (implementation.updated_at) {
438
463
  content += `**Updated:** ${new Date(implementation.updated_at).toLocaleDateString()}\n`;
439
464
  }
@@ -101,7 +101,7 @@ export declare function updateMCPServer(_server: Server, clientFactory: ClientFa
101
101
  items: {
102
102
  type: string;
103
103
  };
104
- description: "Tags for the server. Replaces all existing tags when provided. Use tag slugs.";
104
+ description: "Tags for the server. Providing this replaces ALL existing tags. Omitting leaves them unchanged. Pass an empty array to delete all. Use tag slugs.";
105
105
  };
106
106
  canonical_urls: {
107
107
  type: string;
@@ -124,7 +124,7 @@ export declare function updateMCPServer(_server: Server, clientFactory: ClientFa
124
124
  };
125
125
  required: string[];
126
126
  };
127
- description: "Authoritative URLs for the server. Replaces all existing canonical URLs when provided.";
127
+ description: "Authoritative URLs for the server. Providing this replaces ALL existing canonical URLs. Omitting leaves them unchanged. Pass an empty array to delete all.";
128
128
  };
129
129
  remotes: {
130
130
  type: string;
@@ -177,7 +177,7 @@ export declare function updateMCPServer(_server: Server, clientFactory: ClientFa
177
177
  };
178
178
  };
179
179
  };
180
- description: "Remote endpoints for the server. Replaces all existing remotes when provided.";
180
+ description: "Remote endpoints for the server. Providing this replaces ALL existing remotes. Omitting leaves them unchanged. Pass an empty array to delete all.";
181
181
  };
182
182
  internal_notes: {
183
183
  type: string;
@@ -18,9 +18,9 @@ const PARAM_DESCRIPTIONS = {
18
18
  recommended: 'Mark this server as recommended by PulseMCP',
19
19
  verified_no_remote_canonicals: 'Mark that this server has been verified to have no remote canonical URLs (true = verified no remote canonicals exist, false = reset/canonicals found)',
20
20
  created_on_override: 'Override the automatically derived created date (ISO date string, e.g., "2025-01-15")',
21
- tags: 'Tags for the server. Replaces all existing tags when provided. Use tag slugs.',
22
- canonical_urls: 'Authoritative URLs for the server. Replaces all existing canonical URLs when provided.',
23
- remotes: 'Remote endpoints for the server. Replaces all existing remotes when provided.',
21
+ tags: 'Tags for the server. Providing this replaces ALL existing tags. Omitting leaves them unchanged. Pass an empty array to delete all. Use tag slugs.',
22
+ canonical_urls: 'Authoritative URLs for the server. Providing this replaces ALL existing canonical URLs. Omitting leaves them unchanged. Pass an empty array to delete all.',
23
+ remotes: 'Remote endpoints for the server. Providing this replaces ALL existing remotes. Omitting leaves them unchanged. Pass an empty array to delete all.',
24
24
  internal_notes: 'Admin-only internal notes',
25
25
  };
26
26
  const CanonicalUrlSchema = z.object({
@@ -99,10 +99,15 @@ const UpdateMCPServerSchema = z.object({
99
99
  export function updateMCPServer(_server, clientFactory) {
100
100
  return {
101
101
  name: 'update_mcp_server',
102
- description: `Update an MCP server's information. Only provided fields will be updated.
102
+ description: `Update an MCP server's information. Only provided fields will be updated; **omitted fields remain unchanged**.
103
103
 
104
104
  **Important:** Use the \`implementation_id\` from \`get_mcp_server\` or \`list_mcp_servers\`, NOT the server ID or slug.
105
105
 
106
+ ## Omission semantics
107
+ - **Omitting** \`remotes\`, \`canonical_urls\`, or \`tags\` leaves existing values **unchanged** (does NOT clear them)
108
+ - **Providing** \`remotes\`, \`canonical_urls\`, or \`tags\` **replaces ALL** existing entries (not a merge)
109
+ - To **delete all** entries, pass an empty array (e.g., \`"remotes": []\`)
110
+
106
111
  ## Updating Basic Info
107
112
  \`\`\`json
108
113
  {
@@ -126,7 +131,7 @@ export function updateMCPServer(_server, clientFactory) {
126
131
  \`\`\`
127
132
 
128
133
  ## Adding/Updating Canonical URLs
129
- Providing canonical_urls replaces ALL existing canonical URLs:
134
+ Providing canonical_urls replaces ALL existing canonical URLs (omitting leaves them unchanged):
130
135
  \`\`\`json
131
136
  {
132
137
  "implementation_id": 456,
@@ -138,7 +143,7 @@ Providing canonical_urls replaces ALL existing canonical URLs:
138
143
  \`\`\`
139
144
 
140
145
  ## Adding/Updating Remote Endpoints
141
- Providing remotes replaces ALL existing remote endpoints:
146
+ Providing remotes replaces ALL existing remote endpoints (omitting leaves them unchanged):
142
147
  \`\`\`json
143
148
  {
144
149
  "implementation_id": 456,
package/shared/types.d.ts CHANGED
@@ -714,6 +714,8 @@ export interface ProctorRun {
714
714
  num_tools: number | null;
715
715
  packages: string[];
716
716
  remotes: string[];
717
+ known_missing_init_tools_list: boolean;
718
+ known_missing_auth_check: boolean;
717
719
  }
718
720
  export interface ProctorRunsResponse {
719
721
  runs: ProctorRun[];