opencode-lazy-loader 1.0.0 → 1.0.1

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.
@@ -0,0 +1,19 @@
1
+ import type { Plugin } from '@opencode-ai/plugin';
2
+ /**
3
+ * OpenCode Embedded Skill MCP Plugin
4
+ *
5
+ * Provides skill-embedded MCP support for OpenCode without requiring oh-my-opencode.
6
+ *
7
+ * Features:
8
+ * - Discovers skills from .opencode/skill/ (project) and ~/.config/opencode/skill/ (user)
9
+ * - Parses MCP configurations from YAML frontmatter or mcp.json files
10
+ * - Provides 'skill' tool to load skill instructions and discover MCP capabilities
11
+ * - Provides 'skill_mcp' tool to invoke MCP operations (tools, resources, prompts)
12
+ * - Manages MCP client connections with pooling, lazy initialization, and cleanup
13
+ */
14
+ export declare const OpenCodeEmbeddedSkillMcp: Plugin;
15
+ export default OpenCodeEmbeddedSkillMcp;
16
+ export type { LoadedSkill, McpServerConfig, SkillScope } from './types.js';
17
+ export { discoverSkills } from './skill-loader.js';
18
+ export { createSkillMcpManager } from './skill-mcp-manager.js';
19
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,qBAAqB,CAAA;AAOjD;;;;;;;;;;;GAWG;AACH,eAAO,MAAM,wBAAwB,EAAE,MAwCtC,CAAA;AAGD,eAAe,wBAAwB,CAAA;AAGvC,YAAY,EAAE,WAAW,EAAE,eAAe,EAAE,UAAU,EAAE,MAAM,YAAY,CAAA;AAC1E,OAAO,EAAE,cAAc,EAAE,MAAM,mBAAmB,CAAA;AAClD,OAAO,EAAE,qBAAqB,EAAE,MAAM,wBAAwB,CAAA"}
package/dist/index.js ADDED
@@ -0,0 +1,59 @@
1
+ import { createSkillMcpManager } from './skill-mcp-manager.js';
2
+ import { discoverSkills } from './skill-loader.js';
3
+ import { createSkillTool } from './tools/skill.js';
4
+ import { createSkillMcpTool } from './tools/skill-mcp.js';
5
+ /**
6
+ * OpenCode Embedded Skill MCP Plugin
7
+ *
8
+ * Provides skill-embedded MCP support for OpenCode without requiring oh-my-opencode.
9
+ *
10
+ * Features:
11
+ * - Discovers skills from .opencode/skill/ (project) and ~/.config/opencode/skill/ (user)
12
+ * - Parses MCP configurations from YAML frontmatter or mcp.json files
13
+ * - Provides 'skill' tool to load skill instructions and discover MCP capabilities
14
+ * - Provides 'skill_mcp' tool to invoke MCP operations (tools, resources, prompts)
15
+ * - Manages MCP client connections with pooling, lazy initialization, and cleanup
16
+ */
17
+ export const OpenCodeEmbeddedSkillMcp = async ({ client }) => {
18
+ const manager = createSkillMcpManager();
19
+ let loadedSkills = [];
20
+ let currentSessionID = null;
21
+ // Discover skills on initialization
22
+ try {
23
+ loadedSkills = await discoverSkills();
24
+ }
25
+ catch {
26
+ loadedSkills = [];
27
+ }
28
+ return {
29
+ // Handle session lifecycle events
30
+ event: async ({ event }) => {
31
+ if (event.type === 'session.created') {
32
+ currentSessionID = event.properties.info.id;
33
+ }
34
+ if (event.type === 'session.deleted' && currentSessionID) {
35
+ // Cleanup MCP connections for the deleted session
36
+ await manager.disconnectSession(currentSessionID);
37
+ currentSessionID = null;
38
+ }
39
+ },
40
+ // Register tools
41
+ tool: {
42
+ skill: createSkillTool({
43
+ skills: loadedSkills,
44
+ mcpManager: manager,
45
+ getSessionID: () => currentSessionID || 'unknown'
46
+ }),
47
+ skill_mcp: createSkillMcpTool({
48
+ manager,
49
+ getLoadedSkills: () => loadedSkills,
50
+ getSessionID: () => currentSessionID || 'unknown'
51
+ })
52
+ }
53
+ };
54
+ };
55
+ // Default export for plugin loading
56
+ export default OpenCodeEmbeddedSkillMcp;
57
+ export { discoverSkills } from './skill-loader.js';
58
+ export { createSkillMcpManager } from './skill-mcp-manager.js';
59
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,qBAAqB,EAAE,MAAM,wBAAwB,CAAA;AAC9D,OAAO,EAAE,cAAc,EAAE,MAAM,mBAAmB,CAAA;AAClD,OAAO,EAAE,eAAe,EAAE,MAAM,kBAAkB,CAAA;AAClD,OAAO,EAAE,kBAAkB,EAAE,MAAM,sBAAsB,CAAA;AAGzD;;;;;;;;;;;GAWG;AACH,MAAM,CAAC,MAAM,wBAAwB,GAAW,KAAK,EAAE,EAAE,MAAM,EAAE,EAAE,EAAE;IACnE,MAAM,OAAO,GAAG,qBAAqB,EAAE,CAAA;IACvC,IAAI,YAAY,GAAkB,EAAE,CAAA;IACpC,IAAI,gBAAgB,GAAkB,IAAI,CAAA;IAE1C,oCAAoC;IACpC,IAAI,CAAC;QACH,YAAY,GAAG,MAAM,cAAc,EAAE,CAAA;IACvC,CAAC;IAAC,MAAM,CAAC;QACP,YAAY,GAAG,EAAE,CAAA;IACnB,CAAC;IAED,OAAO;QACL,kCAAkC;QAClC,KAAK,EAAE,KAAK,EAAE,EAAE,KAAK,EAAE,EAAE,EAAE;YACzB,IAAI,KAAK,CAAC,IAAI,KAAK,iBAAiB,EAAE,CAAC;gBACrC,gBAAgB,GAAG,KAAK,CAAC,UAAU,CAAC,IAAI,CAAC,EAAE,CAAA;YAC7C,CAAC;YAED,IAAI,KAAK,CAAC,IAAI,KAAK,iBAAiB,IAAI,gBAAgB,EAAE,CAAC;gBACzD,kDAAkD;gBAClD,MAAM,OAAO,CAAC,iBAAiB,CAAC,gBAAgB,CAAC,CAAA;gBACjD,gBAAgB,GAAG,IAAI,CAAA;YACzB,CAAC;QACH,CAAC;QAED,iBAAiB;QACjB,IAAI,EAAE;YACJ,KAAK,EAAE,eAAe,CAAC;gBACrB,MAAM,EAAE,YAAY;gBACpB,UAAU,EAAE,OAAO;gBACnB,YAAY,EAAE,GAAG,EAAE,CAAC,gBAAgB,IAAI,SAAS;aAClD,CAAC;YACF,SAAS,EAAE,kBAAkB,CAAC;gBAC5B,OAAO;gBACP,eAAe,EAAE,GAAG,EAAE,CAAC,YAAY;gBACnC,YAAY,EAAE,GAAG,EAAE,CAAC,gBAAgB,IAAI,SAAS;aAClD,CAAC;SACH;KACF,CAAA;AACH,CAAC,CAAA;AAED,oCAAoC;AACpC,eAAe,wBAAwB,CAAA;AAIvC,OAAO,EAAE,cAAc,EAAE,MAAM,mBAAmB,CAAA;AAClD,OAAO,EAAE,qBAAqB,EAAE,MAAM,wBAAwB,CAAA"}
@@ -0,0 +1,27 @@
1
+ import type { LoadedSkill, McpServerConfig, SkillScope } from './types.js';
2
+ /**
3
+ * Load MCP config from mcp.json file in skill directory
4
+ */
5
+ export declare function loadMcpJsonFromDir(skillDir: string): Promise<Record<string, McpServerConfig> | undefined>;
6
+ /**
7
+ * Load a skill from a markdown file path
8
+ */
9
+ export declare function loadSkillFromPath(skillPath: string, resolvedPath: string, defaultName: string, scope: SkillScope): Promise<LoadedSkill | null>;
10
+ /**
11
+ * Load all skills from a directory
12
+ */
13
+ export declare function loadSkillsFromDir(skillsDir: string, scope: SkillScope): Promise<LoadedSkill[]>;
14
+ /**
15
+ * Discover skills from opencode global directory (~/.config/opencode/skill/)
16
+ */
17
+ export declare function discoverOpencodeGlobalSkills(): Promise<LoadedSkill[]>;
18
+ /**
19
+ * Discover skills from opencode project directory (.opencode/skill/)
20
+ */
21
+ export declare function discoverOpencodeProjectSkills(): Promise<LoadedSkill[]>;
22
+ /**
23
+ * Discover all skills from both opencode locations
24
+ * Priority: project > global
25
+ */
26
+ export declare function discoverSkills(): Promise<LoadedSkill[]>;
27
+ //# sourceMappingURL=skill-loader.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"skill-loader.d.ts","sourceRoot":"","sources":["../src/skill-loader.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,WAAW,EAAE,eAAe,EAAE,UAAU,EAAe,MAAM,YAAY,CAAA;AAsBvF;;GAEG;AACH,wBAAsB,kBAAkB,CACtC,QAAQ,EAAE,MAAM,GACf,OAAO,CAAC,MAAM,CAAC,MAAM,EAAE,eAAe,CAAC,GAAG,SAAS,CAAC,CA+BtD;AAED;;GAEG;AACH,wBAAsB,iBAAiB,CACrC,SAAS,EAAE,MAAM,EACjB,YAAY,EAAE,MAAM,EACpB,WAAW,EAAE,MAAM,EACnB,KAAK,EAAE,UAAU,GAChB,OAAO,CAAC,WAAW,GAAG,IAAI,CAAC,CAsD7B;AAED;;GAEG;AACH,wBAAsB,iBAAiB,CACrC,SAAS,EAAE,MAAM,EACjB,KAAK,EAAE,UAAU,GAChB,OAAO,CAAC,WAAW,EAAE,CAAC,CAyDxB;AAED;;GAEG;AACH,wBAAsB,4BAA4B,IAAI,OAAO,CAAC,WAAW,EAAE,CAAC,CAG3E;AAED;;GAEG;AACH,wBAAsB,6BAA6B,IAAI,OAAO,CAAC,WAAW,EAAE,CAAC,CAG5E;AAED;;;GAGG;AACH,wBAAsB,cAAc,IAAI,OAAO,CAAC,WAAW,EAAE,CAAC,CAoB7D"}
@@ -0,0 +1,197 @@
1
+ import { promises as fs } from 'fs';
2
+ import { join, basename } from 'path';
3
+ import { homedir } from 'os';
4
+ import { parseFrontmatter, parseSkillMcpConfigFromFrontmatter } from './utils/frontmatter.js';
5
+ /**
6
+ * Check if a file is a markdown file
7
+ */
8
+ function isMarkdownFile(entry) {
9
+ return entry.name.endsWith('.md');
10
+ }
11
+ /**
12
+ * Resolve symlink to its target path
13
+ */
14
+ async function resolveSymlinkAsync(entryPath) {
15
+ try {
16
+ const realPath = await fs.realpath(entryPath);
17
+ return realPath;
18
+ }
19
+ catch {
20
+ return entryPath;
21
+ }
22
+ }
23
+ /**
24
+ * Load MCP config from mcp.json file in skill directory
25
+ */
26
+ export async function loadMcpJsonFromDir(skillDir) {
27
+ const mcpJsonPath = join(skillDir, 'mcp.json');
28
+ try {
29
+ const content = await fs.readFile(mcpJsonPath, 'utf-8');
30
+ const parsed = JSON.parse(content);
31
+ // Support { mcpServers: { ... } } format
32
+ if (parsed && typeof parsed === 'object' && 'mcpServers' in parsed && parsed.mcpServers) {
33
+ return parsed.mcpServers;
34
+ }
35
+ // Support { mcp: { ... } } format (OpenCode config style)
36
+ if (parsed && typeof parsed === 'object' && 'mcp' in parsed && parsed.mcp) {
37
+ return parsed.mcp;
38
+ }
39
+ // Support direct { serverName: { command: ... } } format
40
+ if (parsed && typeof parsed === 'object' && !('mcpServers' in parsed) && !('mcp' in parsed)) {
41
+ const hasCommandField = Object.values(parsed).some((v) => v && typeof v === 'object' && 'command' in v);
42
+ if (hasCommandField) {
43
+ return parsed;
44
+ }
45
+ }
46
+ }
47
+ catch {
48
+ return undefined;
49
+ }
50
+ return undefined;
51
+ }
52
+ /**
53
+ * Load a skill from a markdown file path
54
+ */
55
+ export async function loadSkillFromPath(skillPath, resolvedPath, defaultName, scope) {
56
+ try {
57
+ const content = await fs.readFile(skillPath, 'utf-8');
58
+ const { data } = parseFrontmatter(content);
59
+ // Load MCP config from frontmatter or mcp.json
60
+ const frontmatterMcp = parseSkillMcpConfigFromFrontmatter(content);
61
+ const mcpJsonMcp = await loadMcpJsonFromDir(resolvedPath);
62
+ const mcpConfig = mcpJsonMcp || frontmatterMcp; // mcp.json takes priority
63
+ const skillName = data.name || defaultName;
64
+ const originalDescription = data.description || '';
65
+ const formattedDescription = `(${scope} - Skill) ${originalDescription}`;
66
+ // Create lazy content loader
67
+ const lazyContent = {
68
+ loaded: false,
69
+ content: undefined,
70
+ load: async () => {
71
+ if (!lazyContent.loaded) {
72
+ const fileContent = await fs.readFile(skillPath, 'utf-8');
73
+ const { body } = parseFrontmatter(fileContent);
74
+ lazyContent.content = `<skill-instruction>
75
+ Base directory for this skill: ${resolvedPath}/
76
+ File references (@path) in this skill are relative to this directory.
77
+
78
+ ${body.trim()}
79
+ </skill-instruction>
80
+
81
+ <user-request>
82
+ $ARGUMENTS
83
+ </user-request>`;
84
+ lazyContent.loaded = true;
85
+ }
86
+ return lazyContent.content;
87
+ }
88
+ };
89
+ return {
90
+ name: skillName,
91
+ path: skillPath,
92
+ resolvedPath,
93
+ definition: {
94
+ name: skillName,
95
+ description: formattedDescription,
96
+ template: ''
97
+ },
98
+ scope,
99
+ mcpConfig,
100
+ lazyContent
101
+ };
102
+ }
103
+ catch {
104
+ return null;
105
+ }
106
+ }
107
+ /**
108
+ * Load all skills from a directory
109
+ */
110
+ export async function loadSkillsFromDir(skillsDir, scope) {
111
+ const entries = await fs.readdir(skillsDir, { withFileTypes: true }).catch(() => []);
112
+ const skills = [];
113
+ for (const entry of entries) {
114
+ // Skip hidden files
115
+ if (entry.name.startsWith('.')) {
116
+ continue;
117
+ }
118
+ const entryPath = join(skillsDir, entry.name);
119
+ // Handle directories (skill folders)
120
+ if (entry.isDirectory() || entry.isSymbolicLink()) {
121
+ const resolvedPath = await resolveSymlinkAsync(entryPath);
122
+ const dirName = entry.name;
123
+ // Try SKILL.md first
124
+ const skillMdPath = join(resolvedPath, 'SKILL.md');
125
+ try {
126
+ await fs.access(skillMdPath);
127
+ const skill = await loadSkillFromPath(skillMdPath, resolvedPath, dirName, scope);
128
+ if (skill) {
129
+ skills.push(skill);
130
+ }
131
+ continue;
132
+ }
133
+ catch {
134
+ // SKILL.md not found, try {dirname}.md
135
+ }
136
+ // Try {dirname}.md
137
+ const namedSkillMdPath = join(resolvedPath, `${dirName}.md`);
138
+ try {
139
+ await fs.access(namedSkillMdPath);
140
+ const skill = await loadSkillFromPath(namedSkillMdPath, resolvedPath, dirName, scope);
141
+ if (skill) {
142
+ skills.push(skill);
143
+ }
144
+ continue;
145
+ }
146
+ catch {
147
+ // Named skill file not found
148
+ }
149
+ continue;
150
+ }
151
+ // Handle standalone markdown files
152
+ if (isMarkdownFile(entry)) {
153
+ const skillName = basename(entry.name, '.md');
154
+ const skill = await loadSkillFromPath(entryPath, skillsDir, skillName, scope);
155
+ if (skill) {
156
+ skills.push(skill);
157
+ }
158
+ }
159
+ }
160
+ return skills;
161
+ }
162
+ /**
163
+ * Discover skills from opencode global directory (~/.config/opencode/skill/)
164
+ */
165
+ export async function discoverOpencodeGlobalSkills() {
166
+ const opencodeSkillsDir = join(homedir(), '.config', 'opencode', 'skill');
167
+ return loadSkillsFromDir(opencodeSkillsDir, 'opencode');
168
+ }
169
+ /**
170
+ * Discover skills from opencode project directory (.opencode/skill/)
171
+ */
172
+ export async function discoverOpencodeProjectSkills() {
173
+ const opencodeProjectDir = join(process.cwd(), '.opencode', 'skill');
174
+ return loadSkillsFromDir(opencodeProjectDir, 'opencode-project');
175
+ }
176
+ /**
177
+ * Discover all skills from both opencode locations
178
+ * Priority: project > global
179
+ */
180
+ export async function discoverSkills() {
181
+ const [projectSkills, globalSkills] = await Promise.all([
182
+ discoverOpencodeProjectSkills(),
183
+ discoverOpencodeGlobalSkills()
184
+ ]);
185
+ // Project skills take priority - dedupe by name
186
+ const skillMap = new Map();
187
+ // Add global skills first
188
+ for (const skill of globalSkills) {
189
+ skillMap.set(skill.name, skill);
190
+ }
191
+ // Project skills override global
192
+ for (const skill of projectSkills) {
193
+ skillMap.set(skill.name, skill);
194
+ }
195
+ return Array.from(skillMap.values());
196
+ }
197
+ //# sourceMappingURL=skill-loader.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"skill-loader.js","sourceRoot":"","sources":["../src/skill-loader.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,26 @@
1
+ import { Client } from '@modelcontextprotocol/sdk/client/index.js';
2
+ import type { McpClientInfo, McpContext, McpServerConfig } from './types.js';
3
+ export interface SkillMcpManager {
4
+ getOrCreateClient(info: McpClientInfo, config: McpServerConfig): Promise<Client>;
5
+ disconnectSession(sessionID: string): Promise<void>;
6
+ disconnectAll(): Promise<void>;
7
+ listTools(info: McpClientInfo, context: McpContext): Promise<unknown[]>;
8
+ listResources(info: McpClientInfo, context: McpContext): Promise<unknown[]>;
9
+ listPrompts(info: McpClientInfo, context: McpContext): Promise<unknown[]>;
10
+ callTool(info: McpClientInfo, context: McpContext, name: string, args: Record<string, unknown>): Promise<unknown>;
11
+ readResource(info: McpClientInfo, context: McpContext, uri: string): Promise<unknown>;
12
+ getPrompt(info: McpClientInfo, context: McpContext, name: string, args: Record<string, string>): Promise<unknown>;
13
+ getConnectedServers(): string[];
14
+ isConnected(info: McpClientInfo): boolean;
15
+ }
16
+ /**
17
+ * Create a SkillMcpManager instance
18
+ *
19
+ * Features:
20
+ * - Connection pooling keyed by session/skill/server
21
+ * - Lazy connection creation
22
+ * - Idle cleanup after 5 minutes
23
+ * - Session/process cleanup
24
+ */
25
+ export declare function createSkillMcpManager(): SkillMcpManager;
26
+ //# sourceMappingURL=skill-mcp-manager.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"skill-mcp-manager.d.ts","sourceRoot":"","sources":["../src/skill-mcp-manager.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,EAAE,MAAM,2CAA2C,CAAA;AAElE,OAAO,KAAK,EAAE,aAAa,EAAE,UAAU,EAAE,eAAe,EAAE,MAAM,YAAY,CAAA;AAU5E,MAAM,WAAW,eAAe;IAC9B,iBAAiB,CAAC,IAAI,EAAE,aAAa,EAAE,MAAM,EAAE,eAAe,GAAG,OAAO,CAAC,MAAM,CAAC,CAAA;IAChF,iBAAiB,CAAC,SAAS,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAAA;IACnD,aAAa,IAAI,OAAO,CAAC,IAAI,CAAC,CAAA;IAC9B,SAAS,CAAC,IAAI,EAAE,aAAa,EAAE,OAAO,EAAE,UAAU,GAAG,OAAO,CAAC,OAAO,EAAE,CAAC,CAAA;IACvE,aAAa,CAAC,IAAI,EAAE,aAAa,EAAE,OAAO,EAAE,UAAU,GAAG,OAAO,CAAC,OAAO,EAAE,CAAC,CAAA;IAC3E,WAAW,CAAC,IAAI,EAAE,aAAa,EAAE,OAAO,EAAE,UAAU,GAAG,OAAO,CAAC,OAAO,EAAE,CAAC,CAAA;IACzE,QAAQ,CACN,IAAI,EAAE,aAAa,EACnB,OAAO,EAAE,UAAU,EACnB,IAAI,EAAE,MAAM,EACZ,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAC5B,OAAO,CAAC,OAAO,CAAC,CAAA;IACnB,YAAY,CAAC,IAAI,EAAE,aAAa,EAAE,OAAO,EAAE,UAAU,EAAE,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC,CAAA;IACrF,SAAS,CACP,IAAI,EAAE,aAAa,EACnB,OAAO,EAAE,UAAU,EACnB,IAAI,EAAE,MAAM,EACZ,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,GAC3B,OAAO,CAAC,OAAO,CAAC,CAAA;IACnB,mBAAmB,IAAI,MAAM,EAAE,CAAA;IAC/B,WAAW,CAAC,IAAI,EAAE,aAAa,GAAG,OAAO,CAAA;CAC1C;AAED;;;;;;;;GAQG;AACH,wBAAgB,qBAAqB,IAAI,eAAe,CA0UvD"}
@@ -0,0 +1,284 @@
1
+ import { Client } from '@modelcontextprotocol/sdk/client/index.js';
2
+ import { StdioClientTransport } from '@modelcontextprotocol/sdk/client/stdio.js';
3
+ import { expandEnvVarsInObject, createCleanMcpEnvironment } from './utils/env-vars.js';
4
+ /**
5
+ * Create a SkillMcpManager instance
6
+ *
7
+ * Features:
8
+ * - Connection pooling keyed by session/skill/server
9
+ * - Lazy connection creation
10
+ * - Idle cleanup after 5 minutes
11
+ * - Session/process cleanup
12
+ */
13
+ export function createSkillMcpManager() {
14
+ const clients = new Map();
15
+ const pendingConnections = new Map();
16
+ let cleanupRegistered = false;
17
+ let cleanupInterval = null;
18
+ const IDLE_TIMEOUT = 5 * 60 * 1000; // 5 minutes
19
+ const getClientKey = (info) => {
20
+ return `${info.sessionID}:${info.skillName}:${info.serverName}`;
21
+ };
22
+ const registerProcessCleanup = () => {
23
+ if (cleanupRegistered) {
24
+ return;
25
+ }
26
+ cleanupRegistered = true;
27
+ const cleanup = async () => {
28
+ for (const [, managed] of clients) {
29
+ try {
30
+ await managed.client.close();
31
+ }
32
+ catch {
33
+ // Ignore cleanup errors
34
+ }
35
+ try {
36
+ await managed.transport.close();
37
+ }
38
+ catch {
39
+ // Ignore cleanup errors
40
+ }
41
+ }
42
+ clients.clear();
43
+ pendingConnections.clear();
44
+ };
45
+ process.on('SIGINT', async () => {
46
+ await cleanup();
47
+ process.exit(0);
48
+ });
49
+ process.on('SIGTERM', async () => {
50
+ await cleanup();
51
+ process.exit(0);
52
+ });
53
+ if (process.platform === 'win32') {
54
+ process.on('SIGBREAK', async () => {
55
+ await cleanup();
56
+ process.exit(0);
57
+ });
58
+ }
59
+ };
60
+ const createClient = async (info, config) => {
61
+ const key = getClientKey(info);
62
+ if (!config.command) {
63
+ throw new Error(`MCP server "${info.serverName}" is missing required 'command' field.\n\n` +
64
+ `The MCP configuration in skill "${info.skillName}" must specify a command to execute.\n\n` +
65
+ `Example:\n` +
66
+ ` mcp:\n` +
67
+ ` ${info.serverName}:\n` +
68
+ ` command: ["npx", "-y", "@some/mcp-server"]`);
69
+ }
70
+ const commandValue = config.command;
71
+ const commandParts = Array.isArray(commandValue)
72
+ ? commandValue.map(String)
73
+ : [String(commandValue)];
74
+ const command = commandParts[0];
75
+ const args = commandParts.slice(1);
76
+ const mergedEnv = createCleanMcpEnvironment(config.environment);
77
+ registerProcessCleanup();
78
+ const transport = new StdioClientTransport({
79
+ command,
80
+ args,
81
+ env: mergedEnv,
82
+ stderr: 'ignore'
83
+ });
84
+ const client = new Client({ name: `skill-mcp-${info.skillName}-${info.serverName}`, version: '1.0.0' }, { capabilities: {} });
85
+ try {
86
+ await client.connect(transport);
87
+ }
88
+ catch (error) {
89
+ try {
90
+ await transport.close();
91
+ }
92
+ catch {
93
+ // Ignore cleanup errors
94
+ }
95
+ const errorMessage = error instanceof Error ? error.message : String(error);
96
+ throw new Error(`Failed to connect to MCP server "${info.serverName}".\n\n` +
97
+ `Command: ${command} ${args.join(' ')}\n` +
98
+ `Reason: ${errorMessage}\n\n` +
99
+ `Hints:\n` +
100
+ ` - Ensure the command is installed and available in PATH\n` +
101
+ ` - Check if the MCP server package exists\n` +
102
+ ` - Verify the args are correct for this server`);
103
+ }
104
+ clients.set(key, {
105
+ client,
106
+ transport,
107
+ skillName: info.skillName,
108
+ lastUsedAt: Date.now()
109
+ });
110
+ startCleanupTimer();
111
+ return client;
112
+ };
113
+ const getOrCreateClient = async (info, config) => {
114
+ const key = getClientKey(info);
115
+ const existing = clients.get(key);
116
+ if (existing) {
117
+ existing.lastUsedAt = Date.now();
118
+ return existing.client;
119
+ }
120
+ const pending = pendingConnections.get(key);
121
+ if (pending) {
122
+ return pending;
123
+ }
124
+ const expandedConfig = expandEnvVarsInObject(config);
125
+ const connectionPromise = createClient(info, expandedConfig);
126
+ pendingConnections.set(key, connectionPromise);
127
+ try {
128
+ const client = await connectionPromise;
129
+ return client;
130
+ }
131
+ finally {
132
+ pendingConnections.delete(key);
133
+ }
134
+ };
135
+ const disconnectSession = async (sessionID) => {
136
+ for (const [key, managed] of clients.entries()) {
137
+ if (key.startsWith(`${sessionID}:`)) {
138
+ clients.delete(key);
139
+ try {
140
+ await managed.client.close();
141
+ }
142
+ catch {
143
+ // Ignore cleanup errors
144
+ }
145
+ try {
146
+ await managed.transport.close();
147
+ }
148
+ catch {
149
+ // Ignore cleanup errors
150
+ }
151
+ }
152
+ }
153
+ };
154
+ const disconnectAll = async () => {
155
+ stopCleanupTimer();
156
+ const allClients = Array.from(clients.values());
157
+ clients.clear();
158
+ for (const managed of allClients) {
159
+ try {
160
+ await managed.client.close();
161
+ }
162
+ catch {
163
+ // Ignore cleanup errors
164
+ }
165
+ try {
166
+ await managed.transport.close();
167
+ }
168
+ catch {
169
+ // Ignore cleanup errors
170
+ }
171
+ }
172
+ };
173
+ const startCleanupTimer = () => {
174
+ if (cleanupInterval) {
175
+ return;
176
+ }
177
+ cleanupInterval = setInterval(() => {
178
+ cleanupIdleClients();
179
+ }, 60000);
180
+ cleanupInterval.unref();
181
+ };
182
+ const stopCleanupTimer = () => {
183
+ if (cleanupInterval) {
184
+ clearInterval(cleanupInterval);
185
+ cleanupInterval = null;
186
+ }
187
+ };
188
+ const cleanupIdleClients = async () => {
189
+ const now = Date.now();
190
+ for (const [key, managed] of clients) {
191
+ if (now - managed.lastUsedAt > IDLE_TIMEOUT) {
192
+ clients.delete(key);
193
+ try {
194
+ await managed.client.close();
195
+ }
196
+ catch {
197
+ // Ignore cleanup errors
198
+ }
199
+ try {
200
+ await managed.transport.close();
201
+ }
202
+ catch {
203
+ // Ignore cleanup errors
204
+ }
205
+ }
206
+ }
207
+ };
208
+ const getOrCreateClientWithRetry = async (info, config) => {
209
+ try {
210
+ return await getOrCreateClient(info, config);
211
+ }
212
+ catch (error) {
213
+ const key = getClientKey(info);
214
+ const existing = clients.get(key);
215
+ if (existing) {
216
+ clients.delete(key);
217
+ try {
218
+ await existing.client.close();
219
+ }
220
+ catch {
221
+ // Ignore
222
+ }
223
+ try {
224
+ await existing.transport.close();
225
+ }
226
+ catch {
227
+ // Ignore
228
+ }
229
+ return await getOrCreateClient(info, config);
230
+ }
231
+ throw error;
232
+ }
233
+ };
234
+ const listTools = async (info, context) => {
235
+ const client = await getOrCreateClientWithRetry(info, context.config);
236
+ const result = await client.listTools();
237
+ return result.tools;
238
+ };
239
+ const listResources = async (info, context) => {
240
+ const client = await getOrCreateClientWithRetry(info, context.config);
241
+ const result = await client.listResources();
242
+ return result.resources;
243
+ };
244
+ const listPrompts = async (info, context) => {
245
+ const client = await getOrCreateClientWithRetry(info, context.config);
246
+ const result = await client.listPrompts();
247
+ return result.prompts;
248
+ };
249
+ const callTool = async (info, context, name, args) => {
250
+ const client = await getOrCreateClientWithRetry(info, context.config);
251
+ const result = await client.callTool({ name, arguments: args });
252
+ return result.content;
253
+ };
254
+ const readResource = async (info, context, uri) => {
255
+ const client = await getOrCreateClientWithRetry(info, context.config);
256
+ const result = await client.readResource({ uri });
257
+ return result.contents;
258
+ };
259
+ const getPrompt = async (info, context, name, args) => {
260
+ const client = await getOrCreateClientWithRetry(info, context.config);
261
+ const result = await client.getPrompt({ name, arguments: args });
262
+ return result.messages;
263
+ };
264
+ const getConnectedServers = () => {
265
+ return Array.from(clients.keys());
266
+ };
267
+ const isConnected = (info) => {
268
+ return clients.has(getClientKey(info));
269
+ };
270
+ return {
271
+ getOrCreateClient,
272
+ disconnectSession,
273
+ disconnectAll,
274
+ listTools,
275
+ listResources,
276
+ listPrompts,
277
+ callTool,
278
+ readResource,
279
+ getPrompt,
280
+ getConnectedServers,
281
+ isConnected
282
+ };
283
+ }
284
+ //# sourceMappingURL=skill-mcp-manager.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"skill-mcp-manager.js","sourceRoot":"","sources":["../src/skill-mcp-manager.ts"],"names":[],"mappings":"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"}