@elliotding/ai-agent-mcp 0.1.25 → 0.1.26
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/package.json +4 -1
- package/.prompt-cache/cmd-cmd-client-sdk-ai-hub-generate-testcase.md +0 -101
- package/.prompt-cache/cmd-cmd-client-sdk-ai-hub-submit_zct_job.md +0 -158
- package/.prompt-cache/skill-skill-client-sdk-ai-hub-analyze-conf-status.md +0 -311
- package/.prompt-cache/skill-skill-client-sdk-ai-hub-analyze-sdk-log.md +0 -64
- package/.prompt-cache/skill-skill-client-sdk-ai-hub-analyze-zmb-log-errors.md +0 -84
- package/ai-resource-telemetry.json +0 -40
- package/dist/api/cached-client.d.ts +0 -48
- package/dist/api/cached-client.d.ts.map +0 -1
- package/dist/api/cached-client.js +0 -126
- package/dist/api/cached-client.js.map +0 -1
- package/dist/api/client.d.ts +0 -281
- package/dist/api/client.d.ts.map +0 -1
- package/dist/api/client.js +0 -371
- package/dist/api/client.js.map +0 -1
- package/dist/auth/index.d.ts +0 -8
- package/dist/auth/index.d.ts.map +0 -1
- package/dist/auth/index.js +0 -26
- package/dist/auth/index.js.map +0 -1
- package/dist/auth/middleware.d.ts +0 -36
- package/dist/auth/middleware.d.ts.map +0 -1
- package/dist/auth/middleware.js +0 -194
- package/dist/auth/middleware.js.map +0 -1
- package/dist/auth/permissions.d.ts +0 -60
- package/dist/auth/permissions.d.ts.map +0 -1
- package/dist/auth/permissions.js +0 -262
- package/dist/auth/permissions.js.map +0 -1
- package/dist/auth/token-validator.d.ts +0 -52
- package/dist/auth/token-validator.d.ts.map +0 -1
- package/dist/auth/token-validator.js +0 -215
- package/dist/auth/token-validator.js.map +0 -1
- package/dist/cache/cache-manager.d.ts +0 -49
- package/dist/cache/cache-manager.d.ts.map +0 -1
- package/dist/cache/cache-manager.js +0 -191
- package/dist/cache/cache-manager.js.map +0 -1
- package/dist/cache/index.d.ts +0 -6
- package/dist/cache/index.d.ts.map +0 -1
- package/dist/cache/index.js +0 -12
- package/dist/cache/index.js.map +0 -1
- package/dist/cache/redis-client.d.ts +0 -45
- package/dist/cache/redis-client.d.ts.map +0 -1
- package/dist/cache/redis-client.js +0 -210
- package/dist/cache/redis-client.js.map +0 -1
- package/dist/config/constants.d.ts +0 -28
- package/dist/config/constants.d.ts.map +0 -1
- package/dist/config/constants.js +0 -31
- package/dist/config/constants.js.map +0 -1
- package/dist/config/index.d.ts +0 -71
- package/dist/config/index.d.ts.map +0 -1
- package/dist/config/index.js +0 -190
- package/dist/config/index.js.map +0 -1
- package/dist/filesystem/manager.d.ts +0 -45
- package/dist/filesystem/manager.d.ts.map +0 -1
- package/dist/filesystem/manager.js +0 -246
- package/dist/filesystem/manager.js.map +0 -1
- package/dist/git/multi-source-manager.d.ts +0 -78
- package/dist/git/multi-source-manager.d.ts.map +0 -1
- package/dist/git/multi-source-manager.js +0 -577
- package/dist/git/multi-source-manager.js.map +0 -1
- package/dist/git/operations.d.ts +0 -27
- package/dist/git/operations.d.ts.map +0 -1
- package/dist/git/operations.js +0 -83
- package/dist/git/operations.js.map +0 -1
- package/dist/index.d.ts +0 -6
- package/dist/index.d.ts.map +0 -1
- package/dist/index.js +0 -122
- package/dist/index.js.map +0 -1
- package/dist/monitoring/health.d.ts +0 -35
- package/dist/monitoring/health.d.ts.map +0 -1
- package/dist/monitoring/health.js +0 -105
- package/dist/monitoring/health.js.map +0 -1
- package/dist/prompts/cache.d.ts +0 -69
- package/dist/prompts/cache.d.ts.map +0 -1
- package/dist/prompts/cache.js +0 -163
- package/dist/prompts/cache.js.map +0 -1
- package/dist/prompts/generator.d.ts +0 -49
- package/dist/prompts/generator.d.ts.map +0 -1
- package/dist/prompts/generator.js +0 -160
- package/dist/prompts/generator.js.map +0 -1
- package/dist/prompts/index.d.ts +0 -13
- package/dist/prompts/index.d.ts.map +0 -1
- package/dist/prompts/index.js +0 -24
- package/dist/prompts/index.js.map +0 -1
- package/dist/prompts/manager.d.ts +0 -207
- package/dist/prompts/manager.d.ts.map +0 -1
- package/dist/prompts/manager.js +0 -566
- package/dist/prompts/manager.js.map +0 -1
- package/dist/resources/index.d.ts +0 -6
- package/dist/resources/index.d.ts.map +0 -1
- package/dist/resources/index.js +0 -10
- package/dist/resources/index.js.map +0 -1
- package/dist/resources/loader.d.ts +0 -88
- package/dist/resources/loader.d.ts.map +0 -1
- package/dist/resources/loader.js +0 -492
- package/dist/resources/loader.js.map +0 -1
- package/dist/server/http.d.ts +0 -57
- package/dist/server/http.d.ts.map +0 -1
- package/dist/server/http.js +0 -435
- package/dist/server/http.js.map +0 -1
- package/dist/server.d.ts +0 -13
- package/dist/server.d.ts.map +0 -1
- package/dist/server.js +0 -201
- package/dist/server.js.map +0 -1
- package/dist/session/manager.d.ts +0 -91
- package/dist/session/manager.d.ts.map +0 -1
- package/dist/session/manager.js +0 -251
- package/dist/session/manager.js.map +0 -1
- package/dist/telemetry/index.d.ts +0 -3
- package/dist/telemetry/index.d.ts.map +0 -1
- package/dist/telemetry/index.js +0 -7
- package/dist/telemetry/index.js.map +0 -1
- package/dist/telemetry/manager.d.ts +0 -151
- package/dist/telemetry/manager.d.ts.map +0 -1
- package/dist/telemetry/manager.js +0 -367
- package/dist/telemetry/manager.js.map +0 -1
- package/dist/tools/index.d.ts +0 -13
- package/dist/tools/index.d.ts.map +0 -1
- package/dist/tools/index.js +0 -29
- package/dist/tools/index.js.map +0 -1
- package/dist/tools/manage-subscription.d.ts +0 -47
- package/dist/tools/manage-subscription.d.ts.map +0 -1
- package/dist/tools/manage-subscription.js +0 -317
- package/dist/tools/manage-subscription.js.map +0 -1
- package/dist/tools/registry.d.ts +0 -40
- package/dist/tools/registry.d.ts.map +0 -1
- package/dist/tools/registry.js +0 -85
- package/dist/tools/registry.js.map +0 -1
- package/dist/tools/resolve-prompt-content.d.ts +0 -35
- package/dist/tools/resolve-prompt-content.d.ts.map +0 -1
- package/dist/tools/resolve-prompt-content.js +0 -99
- package/dist/tools/resolve-prompt-content.js.map +0 -1
- package/dist/tools/search-resources.d.ts +0 -35
- package/dist/tools/search-resources.d.ts.map +0 -1
- package/dist/tools/search-resources.js +0 -159
- package/dist/tools/search-resources.js.map +0 -1
- package/dist/tools/sync-resources.d.ts +0 -54
- package/dist/tools/sync-resources.d.ts.map +0 -1
- package/dist/tools/sync-resources.js +0 -735
- package/dist/tools/sync-resources.js.map +0 -1
- package/dist/tools/track-usage.d.ts +0 -63
- package/dist/tools/track-usage.d.ts.map +0 -1
- package/dist/tools/track-usage.js +0 -90
- package/dist/tools/track-usage.js.map +0 -1
- package/dist/tools/uninstall-resource.d.ts +0 -30
- package/dist/tools/uninstall-resource.d.ts.map +0 -1
- package/dist/tools/uninstall-resource.js +0 -174
- package/dist/tools/uninstall-resource.js.map +0 -1
- package/dist/tools/upload-resource.d.ts +0 -81
- package/dist/tools/upload-resource.d.ts.map +0 -1
- package/dist/tools/upload-resource.js +0 -393
- package/dist/tools/upload-resource.js.map +0 -1
- package/dist/transport/sse.d.ts +0 -29
- package/dist/transport/sse.d.ts.map +0 -1
- package/dist/transport/sse.js +0 -271
- package/dist/transport/sse.js.map +0 -1
- package/dist/types/errors.d.ts +0 -60
- package/dist/types/errors.d.ts.map +0 -1
- package/dist/types/errors.js +0 -112
- package/dist/types/errors.js.map +0 -1
- package/dist/types/index.d.ts +0 -7
- package/dist/types/index.d.ts.map +0 -1
- package/dist/types/index.js +0 -23
- package/dist/types/index.js.map +0 -1
- package/dist/types/mcp.d.ts +0 -50
- package/dist/types/mcp.d.ts.map +0 -1
- package/dist/types/mcp.js +0 -6
- package/dist/types/mcp.js.map +0 -1
- package/dist/types/resources.d.ts +0 -109
- package/dist/types/resources.d.ts.map +0 -1
- package/dist/types/resources.js +0 -7
- package/dist/types/resources.js.map +0 -1
- package/dist/types/tools.d.ts +0 -253
- package/dist/types/tools.d.ts.map +0 -1
- package/dist/types/tools.js +0 -6
- package/dist/types/tools.js.map +0 -1
- package/dist/utils/cursor-paths.d.ts +0 -84
- package/dist/utils/cursor-paths.d.ts.map +0 -1
- package/dist/utils/cursor-paths.js +0 -166
- package/dist/utils/cursor-paths.js.map +0 -1
- package/dist/utils/log-cleaner.d.ts +0 -18
- package/dist/utils/log-cleaner.d.ts.map +0 -1
- package/dist/utils/log-cleaner.js +0 -112
- package/dist/utils/log-cleaner.js.map +0 -1
- package/dist/utils/logger.d.ts +0 -59
- package/dist/utils/logger.d.ts.map +0 -1
- package/dist/utils/logger.js +0 -292
- package/dist/utils/logger.js.map +0 -1
- package/dist/utils/validation.d.ts +0 -58
- package/dist/utils/validation.d.ts.map +0 -1
- package/dist/utils/validation.js +0 -214
- package/dist/utils/validation.js.map +0 -1
- package/src/api/cached-client.ts +0 -144
- package/src/api/client.ts +0 -697
- package/src/auth/index.ts +0 -11
- package/src/auth/middleware.ts +0 -244
- package/src/auth/permissions.ts +0 -323
- package/src/auth/token-validator.ts +0 -292
- package/src/cache/cache-manager.ts +0 -243
- package/src/cache/index.ts +0 -6
- package/src/cache/redis-client.ts +0 -249
- package/src/config/constants.ts +0 -33
- package/src/config/index.ts +0 -269
- package/src/filesystem/manager.ts +0 -235
- package/src/git/multi-source-manager.ts +0 -654
- package/src/git/operations.ts +0 -93
- package/src/index.ts +0 -157
- package/src/monitoring/health.ts +0 -132
- package/src/prompts/cache.ts +0 -140
- package/src/prompts/generator.ts +0 -143
- package/src/prompts/index.ts +0 -20
- package/src/prompts/manager.ts +0 -718
- package/src/resources/index.ts +0 -13
- package/src/resources/loader.ts +0 -563
- package/src/server/http.ts +0 -549
- package/src/server.ts +0 -206
- package/src/session/manager.ts +0 -296
- package/src/telemetry/index.ts +0 -10
- package/src/telemetry/manager.ts +0 -419
- package/src/tools/index.ts +0 -13
- package/src/tools/manage-subscription.ts +0 -388
- package/src/tools/registry.ts +0 -97
- package/src/tools/resolve-prompt-content.ts +0 -113
- package/src/tools/search-resources.ts +0 -185
- package/src/tools/sync-resources.ts +0 -829
- package/src/tools/track-usage.ts +0 -113
- package/src/tools/uninstall-resource.ts +0 -199
- package/src/tools/upload-resource.ts +0 -431
- package/src/transport/sse.ts +0 -308
- package/src/types/errors.ts +0 -146
- package/src/types/index.ts +0 -7
- package/src/types/mcp.ts +0 -61
- package/src/types/resources.ts +0 -141
- package/src/types/tools.ts +0 -305
- package/src/utils/cursor-paths.ts +0 -135
- package/src/utils/log-cleaner.ts +0 -92
- package/src/utils/logger.ts +0 -333
- package/src/utils/validation.ts +0 -262
package/src/tools/track-usage.ts
DELETED
|
@@ -1,113 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* track_usage Tool
|
|
3
|
-
*
|
|
4
|
-
* Records an AI Resource invocation for telemetry purposes.
|
|
5
|
-
*
|
|
6
|
-
* This tool is automatically invoked by the AI at the start of every
|
|
7
|
-
* Command or Skill execution. The Prompt content generated by
|
|
8
|
-
* PromptGenerator prepends a system instruction that asks the AI to
|
|
9
|
-
* call `track_usage` before doing anything else, so that the server
|
|
10
|
-
* can record the usage even though Cursor does not call `prompts/get`
|
|
11
|
-
* when a slash command is selected.
|
|
12
|
-
*
|
|
13
|
-
* The tool is intentionally lightweight:
|
|
14
|
-
* - No external API calls.
|
|
15
|
-
* - Fire-and-forget write to the local telemetry file.
|
|
16
|
-
* - Always returns a success response so the AI continues normally.
|
|
17
|
-
*/
|
|
18
|
-
|
|
19
|
-
import { logger } from '../utils/logger';
|
|
20
|
-
import { telemetry } from '../telemetry/index.js';
|
|
21
|
-
import type { ToolResult } from '../types/tools';
|
|
22
|
-
|
|
23
|
-
export interface TrackUsageParams {
|
|
24
|
-
resource_id: string;
|
|
25
|
-
resource_type: 'command' | 'skill';
|
|
26
|
-
resource_name: string;
|
|
27
|
-
/** Automatically injected by the MCP server from the SSE token. */
|
|
28
|
-
user_token?: string;
|
|
29
|
-
/** Optional Jira Issue ID for usage correlation (e.g. "PROJ-12345"). */
|
|
30
|
-
jira_id?: string;
|
|
31
|
-
}
|
|
32
|
-
|
|
33
|
-
export async function trackUsage(params: unknown): Promise<ToolResult<{ recorded: boolean }>> {
|
|
34
|
-
const p = params as TrackUsageParams;
|
|
35
|
-
|
|
36
|
-
const resourceId = p.resource_id ?? '';
|
|
37
|
-
const resourceType = p.resource_type ?? 'command';
|
|
38
|
-
const resourceName = p.resource_name ?? '';
|
|
39
|
-
const userToken = p.user_token ?? '';
|
|
40
|
-
const jiraId = typeof p.jira_id === 'string' && p.jira_id.trim() !== ''
|
|
41
|
-
? p.jira_id.trim()
|
|
42
|
-
: undefined;
|
|
43
|
-
|
|
44
|
-
if (!resourceId || !userToken) {
|
|
45
|
-
// Missing required fields — log and return without recording so the AI
|
|
46
|
-
// is not blocked. This should not happen in normal operation.
|
|
47
|
-
logger.warn(
|
|
48
|
-
{ resourceId, userToken: !!userToken },
|
|
49
|
-
'track_usage called with missing resource_id or user_token — skipping',
|
|
50
|
-
);
|
|
51
|
-
return { success: true, data: { recorded: false } };
|
|
52
|
-
}
|
|
53
|
-
|
|
54
|
-
// Await the write to ensure the event is persisted before the periodic flush
|
|
55
|
-
// timer fires and clears pending_events. File write latency is negligible
|
|
56
|
-
// (< 1 ms) so this does not meaningfully delay the tool response.
|
|
57
|
-
await telemetry
|
|
58
|
-
.recordInvocation(resourceId, resourceType, resourceName, userToken, jiraId)
|
|
59
|
-
.catch((err) => {
|
|
60
|
-
logger.warn({ resourceId, error: (err as Error).message }, 'track_usage: telemetry write failed (non-critical)');
|
|
61
|
-
});
|
|
62
|
-
|
|
63
|
-
logger.info(
|
|
64
|
-
{ resourceId, resourceType, resourceName, jiraId: jiraId ?? '(none)' },
|
|
65
|
-
'track_usage: invocation recorded',
|
|
66
|
-
);
|
|
67
|
-
|
|
68
|
-
return { success: true, data: { recorded: true } };
|
|
69
|
-
}
|
|
70
|
-
|
|
71
|
-
export const trackUsageTool = {
|
|
72
|
-
name: 'track_usage',
|
|
73
|
-
description:
|
|
74
|
-
'Record the invocation of an AI Resource (Command or Skill) for telemetry. ' +
|
|
75
|
-
'MUST be called at the very beginning of every Command or Skill execution, ' +
|
|
76
|
-
'before performing any other action. ' +
|
|
77
|
-
'The resource_id, resource_type, and resource_name are provided in the prompt header — ' +
|
|
78
|
-
'copy them exactly as given. ' +
|
|
79
|
-
'user_token is injected automatically by the server; do NOT ask the user for it. ' +
|
|
80
|
-
'jira_id is optional — only include it if the user explicitly mentions a Jira issue number.',
|
|
81
|
-
inputSchema: {
|
|
82
|
-
type: 'object' as const,
|
|
83
|
-
properties: {
|
|
84
|
-
resource_id: {
|
|
85
|
-
type: 'string',
|
|
86
|
-
description: 'Canonical resource ID as shown in the prompt header (e.g. "cmd-client-sdk-ai-hub-generate-testcase").',
|
|
87
|
-
},
|
|
88
|
-
resource_type: {
|
|
89
|
-
type: 'string',
|
|
90
|
-
enum: ['command', 'skill'],
|
|
91
|
-
description: 'Resource type: "command" or "skill".',
|
|
92
|
-
},
|
|
93
|
-
resource_name: {
|
|
94
|
-
type: 'string',
|
|
95
|
-
description: 'Human-readable resource name as shown in the prompt header (e.g. "generate-testcase").',
|
|
96
|
-
},
|
|
97
|
-
user_token: {
|
|
98
|
-
type: 'string',
|
|
99
|
-
description:
|
|
100
|
-
'DO NOT set this field — it is automatically injected by the MCP server from ' +
|
|
101
|
-
'the authenticated SSE connection.',
|
|
102
|
-
},
|
|
103
|
-
jira_id: {
|
|
104
|
-
type: 'string',
|
|
105
|
-
description:
|
|
106
|
-
'Optional Jira Issue ID for usage correlation (e.g. "PROJ-12345"). ' +
|
|
107
|
-
'Only include if the user explicitly mentioned a Jira issue in this conversation.',
|
|
108
|
-
},
|
|
109
|
-
},
|
|
110
|
-
required: ['resource_id', 'resource_type', 'resource_name'],
|
|
111
|
-
},
|
|
112
|
-
handler: trackUsage,
|
|
113
|
-
};
|
|
@@ -1,199 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* uninstall_resource Tool
|
|
3
|
-
* Uninstall a resource from local filesystem and clean up related configuration.
|
|
4
|
-
*
|
|
5
|
-
* For MCP resources this also removes the mcpServers entry from ~/.cursor/mcp.json.
|
|
6
|
-
* For directory-based resources (skill, mcp) the entire install directory is removed.
|
|
7
|
-
*/
|
|
8
|
-
|
|
9
|
-
import { logger, logToolCall } from '../utils/logger';
|
|
10
|
-
import { apiClient } from '../api/client';
|
|
11
|
-
import { getCursorTypeDirForClient, getCursorRootDirForClient } from '../utils/cursor-paths.js';
|
|
12
|
-
import { MCPServerError, createValidationError } from '../types/errors';
|
|
13
|
-
import type { UninstallResourceParams, UninstallResourceResult, LocalAction, ToolResult } from '../types/tools';
|
|
14
|
-
import { promptManager } from '../prompts/index.js';
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
export async function uninstallResource(params: unknown): Promise<ToolResult<UninstallResourceResult>> {
|
|
18
|
-
const startTime = Date.now();
|
|
19
|
-
const typedParams = params as UninstallResourceParams;
|
|
20
|
-
|
|
21
|
-
logger.info({ tool: 'uninstall_resource', params }, 'uninstall_resource called');
|
|
22
|
-
|
|
23
|
-
try {
|
|
24
|
-
const pattern = typedParams.resource_id_or_name;
|
|
25
|
-
const removeFromAccount = typedParams.remove_from_account || false;
|
|
26
|
-
|
|
27
|
-
const removedResources: Array<{ id: string; name: string; path: string }> = [];
|
|
28
|
-
let subscriptionRemoved = false;
|
|
29
|
-
|
|
30
|
-
// ── Command / Skill: unregister MCP Prompt + delete cache ─────────────
|
|
31
|
-
// Match registered prompt names that contain the pattern.
|
|
32
|
-
const matchedPromptNames = promptManager.promptNames(typedParams.user_token ?? '').filter(
|
|
33
|
-
(name) => name === pattern || name.includes(pattern),
|
|
34
|
-
);
|
|
35
|
-
|
|
36
|
-
if (matchedPromptNames.length > 0) {
|
|
37
|
-
for (const promptName of matchedPromptNames) {
|
|
38
|
-
// Prompt name format: <team>/<type>/<resource_name>
|
|
39
|
-
const parts = promptName.split('/');
|
|
40
|
-
const team = parts[0] ?? 'general';
|
|
41
|
-
const resourceType = parts[1] as 'command' | 'skill' | undefined;
|
|
42
|
-
const resourceName = parts.slice(2).join('/') || promptName;
|
|
43
|
-
|
|
44
|
-
// Find the resource_id from the registered prompt (best-effort via name).
|
|
45
|
-
// For unsubscription, we pass the promptName as id if no better source.
|
|
46
|
-
const resourceId = pattern.startsWith('cmd-') || pattern.startsWith('skill-')
|
|
47
|
-
? pattern
|
|
48
|
-
: promptName;
|
|
49
|
-
|
|
50
|
-
// Unregister from the in-memory prompt registry only.
|
|
51
|
-
// The server-side .prompt-cache/ files are intentionally NOT deleted here —
|
|
52
|
-
// they are shared across all users and will be regenerated on the next git pull.
|
|
53
|
-
promptManager.unregisterPrompt(resourceId, resourceType ?? 'command', resourceName, typedParams.user_token ?? '');
|
|
54
|
-
|
|
55
|
-
removedResources.push({ id: resourceId, name: resourceName, path: `[MCP Prompt: ${promptName}]` });
|
|
56
|
-
logger.info({ promptName, team, resourceType, resourceName }, 'MCP Prompt unregistered via uninstall');
|
|
57
|
-
}
|
|
58
|
-
|
|
59
|
-
// Remove from server subscription if requested
|
|
60
|
-
if (removeFromAccount) {
|
|
61
|
-
for (const r of removedResources) {
|
|
62
|
-
try {
|
|
63
|
-
await apiClient.unsubscribe(r.id);
|
|
64
|
-
subscriptionRemoved = true;
|
|
65
|
-
} catch (err) {
|
|
66
|
-
logger.warn({ resourceId: r.id, err }, 'Failed to unsubscribe Command/Skill Prompt from account');
|
|
67
|
-
}
|
|
68
|
-
}
|
|
69
|
-
}
|
|
70
|
-
|
|
71
|
-
// Return early — Command/Skill resources have no local filesystem footprint.
|
|
72
|
-
const result: UninstallResourceResult = {
|
|
73
|
-
success: true,
|
|
74
|
-
removed_resources: removedResources,
|
|
75
|
-
subscription_removed: subscriptionRemoved,
|
|
76
|
-
message: [
|
|
77
|
-
`Successfully unregistered ${removedResources.length} MCP Prompt${removedResources.length > 1 ? 's' : ''}.`,
|
|
78
|
-
subscriptionRemoved ? 'Subscription removed from account.' : null,
|
|
79
|
-
].filter(Boolean).join(' '),
|
|
80
|
-
};
|
|
81
|
-
const duration = Date.now() - startTime;
|
|
82
|
-
logToolCall('uninstall_resource', 'user-id', params as Record<string, unknown>, duration);
|
|
83
|
-
return { success: true, data: result };
|
|
84
|
-
}
|
|
85
|
-
|
|
86
|
-
// ── Rule / MCP: return LocalAction instructions for the AI to execute ────
|
|
87
|
-
// The MCP server may be running remotely; we must NOT touch the server's
|
|
88
|
-
// own filesystem. Instead we return delete/remove instructions so the AI
|
|
89
|
-
// Agent performs them on the user's LOCAL machine.
|
|
90
|
-
logger.debug({ pattern, resourceType: typedParams.resource_type }, 'Building local uninstall actions for Rule/MCP resource...');
|
|
91
|
-
|
|
92
|
-
const localActions: LocalAction[] = [];
|
|
93
|
-
// Use client-side tilde-based paths; the MCP server may be running remotely
|
|
94
|
-
// and its os.homedir() would resolve to the server's home, not the user's.
|
|
95
|
-
const mcpJsonPath = `${getCursorRootDirForClient()}/mcp.json`;
|
|
96
|
-
|
|
97
|
-
// When resource_type is provided, only emit the relevant actions.
|
|
98
|
-
// When unknown, emit both (AI skips missing files gracefully).
|
|
99
|
-
const knownType = typedParams.resource_type;
|
|
100
|
-
const isRule = !knownType || knownType === 'rule';
|
|
101
|
-
const isMcp = !knownType || knownType === 'mcp';
|
|
102
|
-
|
|
103
|
-
if (isRule) {
|
|
104
|
-
// Rule: delete ~/.cursor/rules/<pattern>.mdc and .md variants.
|
|
105
|
-
const rulesDir = getCursorTypeDirForClient('rule');
|
|
106
|
-
for (const ext of ['.mdc', '.md']) {
|
|
107
|
-
const filePath = `${rulesDir}/${pattern}${ext}`;
|
|
108
|
-
localActions.push({ action: 'delete_file', path: filePath });
|
|
109
|
-
removedResources.push({ id: pattern, name: pattern, path: filePath });
|
|
110
|
-
}
|
|
111
|
-
}
|
|
112
|
-
|
|
113
|
-
if (isMcp) {
|
|
114
|
-
// MCP: delete install directory (Format A — may not exist for remote-URL MCPs)
|
|
115
|
-
// and remove the mcpServers entry from mcp.json.
|
|
116
|
-
const mcpDir = getCursorTypeDirForClient('mcp');
|
|
117
|
-
const mcpInstallDir = `${mcpDir}/${pattern}`;
|
|
118
|
-
localActions.push({ action: 'delete_file', path: mcpInstallDir, recursive: true });
|
|
119
|
-
localActions.push({ action: 'remove_mcp_json_entry', mcp_json_path: mcpJsonPath, server_name: pattern });
|
|
120
|
-
removedResources.push({ id: pattern, name: pattern, path: mcpInstallDir });
|
|
121
|
-
}
|
|
122
|
-
|
|
123
|
-
if (removedResources.length === 0 && localActions.length === 0) {
|
|
124
|
-
throw createValidationError(
|
|
125
|
-
pattern,
|
|
126
|
-
'resource_id_or_name',
|
|
127
|
-
'No installed Rule or MCP resources found matching pattern. Use search_resources to find available resources'
|
|
128
|
-
);
|
|
129
|
-
}
|
|
130
|
-
|
|
131
|
-
// Remove from server subscription if requested
|
|
132
|
-
if (removeFromAccount) {
|
|
133
|
-
try {
|
|
134
|
-
await apiClient.unsubscribe(pattern);
|
|
135
|
-
subscriptionRemoved = true;
|
|
136
|
-
} catch (err) {
|
|
137
|
-
logger.warn({ pattern, err }, 'Failed to unsubscribe resource from account');
|
|
138
|
-
}
|
|
139
|
-
}
|
|
140
|
-
|
|
141
|
-
const result: UninstallResourceResult = {
|
|
142
|
-
success: true,
|
|
143
|
-
removed_resources: removedResources,
|
|
144
|
-
subscription_removed: subscriptionRemoved,
|
|
145
|
-
message: [
|
|
146
|
-
`Prepared ${localActions.length} local uninstall action(s) for ${removedResources.length} resource(s).`,
|
|
147
|
-
'Execute every action in local_actions_required on the user\'s local machine.',
|
|
148
|
-
subscriptionRemoved ? 'Subscription removed from account.' : null,
|
|
149
|
-
].filter(Boolean).join(' '),
|
|
150
|
-
local_actions_required: localActions,
|
|
151
|
-
};
|
|
152
|
-
|
|
153
|
-
const duration = Date.now() - startTime;
|
|
154
|
-
logToolCall('uninstall_resource', 'user-id', params as Record<string, unknown>, duration);
|
|
155
|
-
logger.info({ pattern, actionCount: localActions.length, subscriptionRemoved, duration }, 'uninstall_resource completed');
|
|
156
|
-
|
|
157
|
-
return { success: true, data: result };
|
|
158
|
-
|
|
159
|
-
} catch (error) {
|
|
160
|
-
logger.error({ error, pattern: typedParams.resource_id_or_name }, 'uninstall_resource failed');
|
|
161
|
-
return {
|
|
162
|
-
success: false,
|
|
163
|
-
error: {
|
|
164
|
-
code: error instanceof MCPServerError ? error.code : 'UNKNOWN_ERROR',
|
|
165
|
-
message: error instanceof Error ? error.message : String(error),
|
|
166
|
-
},
|
|
167
|
-
};
|
|
168
|
-
}
|
|
169
|
-
}
|
|
170
|
-
|
|
171
|
-
// Tool definition for registry
|
|
172
|
-
export const uninstallResourceTool = {
|
|
173
|
-
name: 'uninstall_resource',
|
|
174
|
-
description:
|
|
175
|
-
'Uninstall a Rule or MCP resource from the user\'s local machine. ' +
|
|
176
|
-
'Returns `local_actions_required` — an ordered list of delete_file and ' +
|
|
177
|
-
'remove_mcp_json_entry actions that the AI Agent MUST execute on the USER\'S LOCAL MACHINE. ' +
|
|
178
|
-
'For delete_file actions: delete the file or directory at the given path. ' +
|
|
179
|
-
'For remove_mcp_json_entry actions: read ~/.cursor/mcp.json, delete the matching ' +
|
|
180
|
-
'mcpServers key, then write the file back. ' +
|
|
181
|
-
'Command and Skill resources are handled by unregistering their MCP Prompt (no local files). ' +
|
|
182
|
-
'Set remove_from_account: true to also cancel the server-side subscription.',
|
|
183
|
-
inputSchema: {
|
|
184
|
-
type: 'object' as const,
|
|
185
|
-
properties: {
|
|
186
|
-
resource_id_or_name: {
|
|
187
|
-
type: 'string',
|
|
188
|
-
description: 'Resource ID, name, or pattern (supports fuzzy matching)',
|
|
189
|
-
},
|
|
190
|
-
remove_from_account: {
|
|
191
|
-
type: 'boolean',
|
|
192
|
-
description: 'Also remove from subscription list (default: false)',
|
|
193
|
-
default: false,
|
|
194
|
-
},
|
|
195
|
-
},
|
|
196
|
-
required: ['resource_id_or_name'],
|
|
197
|
-
},
|
|
198
|
-
handler: uninstallResource,
|
|
199
|
-
};
|