ring-skills-mcp 1.0.2 → 1.0.4

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.
Files changed (2) hide show
  1. package/dist/index.js +50 -8
  2. package/package.json +1 -1
package/dist/index.js CHANGED
@@ -52,10 +52,19 @@ async function fetchSkills(host, search = "", pageSize = 5000, token = "") {
52
52
  throw new Error("Failed to fetch Skills list: Unknown error");
53
53
  }
54
54
  }
55
+ /**
56
+ * Extract skill name from gitUrl
57
+ * Example: "https://github.com/anthropics/skills/tree/main/skills/webapp-testing" -> "webapp-testing"
58
+ */
59
+ function extractSkillNameFromGitUrl(gitUrl) {
60
+ // Match pattern: .../skills/{skill-name} or .../skills/{skill-name}/...
61
+ const match = gitUrl.match(/\/skills\/([^\/\s]+)/);
62
+ return match ? match[1].toLowerCase() : null;
63
+ }
55
64
  /**
56
65
  * Install Skill to specified project
57
66
  */
58
- async function installSkill(skillName, projectPath, targetDir = "skills", repo = DEFAULT_SKILLS_REPO) {
67
+ async function installSkill(skillName, projectPath, targetDir = ".claude/skills", repo = DEFAULT_SKILLS_REPO) {
59
68
  // Convert skill name to lowercase
60
69
  const normalizedName = skillName.toLowerCase();
61
70
  // Build full installation path
@@ -119,7 +128,8 @@ server.tool("list_skills", "Fetch company Skills list. You can search for specif
119
128
  const title = skill.title || skill.id || "Unnamed";
120
129
  const summary = skill.summary || "No description";
121
130
  const category = skill.category ? ` [${skill.category}]` : "";
122
- return `${index + 1}. **${title}**${category}\n ${summary}`;
131
+ const gitUrl = skill.gitUrl ? ` [${skill.gitUrl}]` : "";
132
+ return `${index + 1}. **${title}**${category}\n ${summary} ${gitUrl}`;
123
133
  })
124
134
  .join("\n\n");
125
135
  return {
@@ -144,8 +154,9 @@ server.tool("list_skills", "Fetch company Skills list. You can search for specif
144
154
  }
145
155
  });
146
156
  // Register tool: Install Skill
147
- server.tool("install_skill", "Install skill to local project by skill name. Uses npx degit to download skill template from remote repository. Project path is required, which can be the project path of the currently opened file in IDE.", {
148
- skillName: z.string().describe("Name of the skill to install"),
157
+ server.tool("install_skill", "Install skill to local project by skill name or gitUrl. Uses npx degit to download skill template from remote repository. Project path is required, which can be the project path of the currently opened file in IDE.", {
158
+ skillName: z.string().optional().describe("Name of the skill to install (e.g., 'webapp-testing'). Either skillName or gitUrl must be provided."),
159
+ gitUrl: z.string().optional().describe("Git URL of the skill (e.g., 'https://github.com/anthropics/skills/tree/main/skills/webapp-testing'). The skill name will be extracted from this URL. Either skillName or gitUrl must be provided."),
149
160
  projectPath: z
150
161
  .string()
151
162
  .optional()
@@ -153,26 +164,57 @@ server.tool("install_skill", "Install skill to local project by skill name. Uses
153
164
  targetDir: z
154
165
  .string()
155
166
  .optional()
156
- .describe("Installation target directory, default: skills"),
167
+ .describe("Installation target directory, default: .claude/skills"),
157
168
  repo: z
158
169
  .string()
159
170
  .optional()
160
171
  .describe(`Skills repository path, default: ${DEFAULT_SKILLS_REPO}`),
161
- }, async ({ skillName, projectPath, targetDir, repo }) => {
172
+ }, async ({ skillName, gitUrl, projectPath, targetDir, repo }) => {
162
173
  // Check if project path is provided
163
174
  if (!projectPath) {
164
175
  return {
165
176
  content: [
166
177
  {
167
178
  type: "text",
168
- text: "❌ Please provide project path (projectPath).\n\nYou can provide the project root directory path of the currently opened file in IDE, skill will be installed to the skills directory of that project.\n\nExample: /Users/xxx/my-project",
179
+ text: "❌ Please provide project path (projectPath).\n\nYou can provide the project root directory path of the currently opened file in IDE, skill will be installed to the .claude/skills directory of that project.\n\nExample: /Users/xxx/my-project",
180
+ },
181
+ ],
182
+ isError: true,
183
+ };
184
+ }
185
+ // Determine the actual skill name to use
186
+ let actualSkillName = null;
187
+ // Priority: gitUrl > skillName
188
+ if (gitUrl) {
189
+ actualSkillName = extractSkillNameFromGitUrl(gitUrl);
190
+ if (!actualSkillName) {
191
+ return {
192
+ content: [
193
+ {
194
+ type: "text",
195
+ text: `❌ Error: Could not extract skill name from gitUrl: ${gitUrl}\n\nExpected format: https://github.com/org/repo/tree/main/skills/{skill-name}`,
196
+ },
197
+ ],
198
+ isError: true,
199
+ };
200
+ }
201
+ }
202
+ else if (skillName) {
203
+ actualSkillName = skillName;
204
+ }
205
+ if (!actualSkillName) {
206
+ return {
207
+ content: [
208
+ {
209
+ type: "text",
210
+ text: "❌ Error: Either skillName or gitUrl must be provided.",
169
211
  },
170
212
  ],
171
213
  isError: true,
172
214
  };
173
215
  }
174
216
  try {
175
- const result = await installSkill(skillName, projectPath, targetDir || "skills", repo || DEFAULT_SKILLS_REPO);
217
+ const result = await installSkill(actualSkillName, projectPath, targetDir || ".claude/skills", repo || DEFAULT_SKILLS_REPO);
176
218
  return {
177
219
  content: [
178
220
  {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "ring-skills-mcp",
3
- "version": "1.0.2",
3
+ "version": "1.0.4",
4
4
  "description": "MCP service for fetching and installing company Skills",
5
5
  "type": "module",
6
6
  "main": "dist/index.js",