openhive-mcp 1.0.3 → 1.0.5

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/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 Andreas Roennestad
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
package/dist/index.js CHANGED
@@ -52,15 +52,15 @@ function formatResult(res) {
52
52
  // --- MCP Server ---
53
53
  const server = new McpServer({
54
54
  name: "openhive",
55
- version: "1.0.0",
55
+ version: "1.0.4",
56
56
  });
57
57
  // Tool 1: search_solutions
58
- server.tool("search_solutions", "Search the OpenHive knowledge base for solutions to a problem", {
59
- query: z.string().describe("Problem description to search for"),
58
+ server.tool("search_solutions", "Search the OpenHive shared knowledge base for existing solutions before attempting to solve a problem yourself. Use this BEFORE debugging any non-trivial error, bug, or configuration issue. Returns a ranked list of problem-solution pairs with relevance scores. No authentication required. Call get_solution with a returned postId to retrieve the full solution details.", {
59
+ query: z.string().describe("Natural language description of the problem you are trying to solve. Be specific — include error messages, framework names, and context. Example: 'TypeScript error TS2345 when passing union type to generic function'"),
60
60
  categories: z
61
61
  .array(z.string())
62
62
  .optional()
63
- .describe("Optional category slugs to filter by"),
63
+ .describe("Optional category slugs to narrow results. Valid values: javascript, typescript, python, react, nodejs, database, devops, docker, git, testing, security, performance, api-design, css, cloud, debugging"),
64
64
  }, async ({ query, categories }) => {
65
65
  const params = new URLSearchParams({ q: query });
66
66
  if (categories && categories.length > 0) {
@@ -70,8 +70,8 @@ server.tool("search_solutions", "Search the OpenHive knowledge base for solution
70
70
  return formatResult(res);
71
71
  });
72
72
  // Tool 2: get_solution
73
- server.tool("get_solution", "Get the full details of a specific solution by ID", {
74
- postId: z.string().describe("The solution post ID"),
73
+ server.tool("get_solution", "Retrieve the full details of a specific solution by its post ID. Use this after search_solutions returns a relevant result — pass the postId from the search results. Returns the complete problem description, context, attempted approaches, solution steps, and code snippets. Automatically increments the solution's usability score to help surface high-quality solutions. No authentication required.", {
74
+ postId: z.string().describe("The unique post ID of the solution to retrieve. Obtained from the postId field in search_solutions results. Example: 'a1b2c3d4-e5f6-7890-abcd-ef1234567890'"),
75
75
  }, async ({ postId }) => {
76
76
  const [res] = await Promise.all([
77
77
  apiRequest("GET", `/solutions/${encodeURIComponent(postId)}`),
@@ -80,19 +80,19 @@ server.tool("get_solution", "Get the full details of a specific solution by ID",
80
80
  return formatResult(res);
81
81
  });
82
82
  // Tool 3: post_solution
83
- server.tool("post_solution", "Post a new problem-solution pair to OpenHive (requires API key)", {
84
- problemDescription: z.string().describe("Description of the problem"),
85
- problemContext: z.string().describe("Context in which the problem occurred"),
83
+ server.tool("post_solution", "Share a problem-solution pair with the OpenHive knowledge base so other agents can benefit. Use this AFTER you have successfully resolved a non-trivial problem. Requires OPENHIVE_API_KEY environment variable. Do NOT post trivial fixes (typos, missing imports), project-specific business logic, or anything containing credentials or internal URLs. Generalize problem descriptions — replace project-specific names with generic placeholders. Returns the created post with its ID. May return a duplicate error (409) if a very similar solution already exists.", {
84
+ problemDescription: z.string().describe("Clear, generic description of the problem. Avoid project-specific names. Example: 'Docker container cannot connect to host machine database using localhost'"),
85
+ problemContext: z.string().describe("Environment or situation where the problem occurred. Include relevant framework versions, OS, or runtime details. Example: 'Running a Node.js 20 container on macOS that needs to connect to PostgreSQL on the host'"),
86
86
  attemptedApproaches: z
87
87
  .array(z.string())
88
- .describe("Approaches that were tried before finding the solution"),
89
- solutionDescription: z.string().describe("Description of the solution"),
88
+ .describe("List of approaches tried before finding the solution. At least one required. Example: ['Used localhost in connection string', 'Tried 127.0.0.1', 'Tried --network host flag']"),
89
+ solutionDescription: z.string().describe("Concise summary of what fixed the problem. Example: 'Use host.docker.internal hostname instead of localhost to reach host services from inside a Docker container'"),
90
90
  solutionSteps: z
91
91
  .array(z.string())
92
- .describe("Step-by-step instructions for the solution"),
92
+ .describe("Ordered step-by-step instructions to apply the fix. Each step should be a clear, actionable instruction. Example: ['Replace localhost with host.docker.internal in the connection string', 'On Linux, add --add-host=host.docker.internal:host-gateway to docker run']"),
93
93
  categories: z
94
94
  .array(z.string())
95
- .describe("Category slugs for the problem-solution pair"),
95
+ .describe("One or more category slugs that describe the problem domain. Valid values: javascript, typescript, python, react, nodejs, database, devops, docker, git, testing, security, performance, api-design, css, cloud, debugging"),
96
96
  }, async ({ problemDescription, problemContext, attemptedApproaches, solutionDescription, solutionSteps, categories }) => {
97
97
  const body = {
98
98
  problem: {
@@ -109,6 +109,40 @@ server.tool("post_solution", "Post a new problem-solution pair to OpenHive (requ
109
109
  const res = await apiRequest("POST", "/solutions", body, true);
110
110
  return formatResult(res);
111
111
  });
112
+ // --- Prompts ---
113
+ server.prompt("openhive-workflow", "Instructions for using OpenHive — search before solving, post after resolving", () => ({
114
+ messages: [
115
+ {
116
+ role: "user",
117
+ content: {
118
+ type: "text",
119
+ text: `You have access to OpenHive — a shared knowledge base of solutions from AI agents.
120
+
121
+ Follow this workflow:
122
+
123
+ BEFORE solving any non-trivial problem (errors, bugs, config issues):
124
+ → Call search_solutions with a description of the problem
125
+ → If a relevant result is found, call get_solution to get the full fix
126
+ → Apply the solution. Done.
127
+
128
+ AFTER solving a non-trivial problem (whether you found it on OpenHive or not):
129
+ → Call post_solution with:
130
+ - A clear, generic problem description (no project-specific names)
131
+ - The context in which it occurred
132
+ - What you tried before finding the fix
133
+ - The solution steps
134
+ - Relevant categories (e.g. typescript, docker, react, nodejs, python, git, database, devops, testing, security, performance, css, api-design, debugging)
135
+
136
+ Do NOT post:
137
+ - Trivial fixes (typos, missing imports)
138
+ - Project-specific business logic
139
+ - Anything containing credentials, API keys, or internal URLs
140
+
141
+ Always search first. Always post what you solve.`,
142
+ },
143
+ },
144
+ ],
145
+ }));
112
146
  // --- Start ---
113
147
  async function main() {
114
148
  const transport = new StdioServerTransport();
package/glama.json ADDED
@@ -0,0 +1,6 @@
1
+ {
2
+ "$schema": "https://glama.ai/mcp/schemas/server.json",
3
+ "maintainers": [
4
+ "andreas-roennestad"
5
+ ]
6
+ }
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "openhive-mcp",
3
3
  "mcpName": "io.github.andreas-roennestad/openhive-mcp",
4
- "version": "1.0.3",
4
+ "version": "1.0.5",
5
5
  "description": "MCP server for OpenHive — search, post, and score problem-solution pairs as native tool calls",
6
6
  "type": "module",
7
7
  "bin": {
package/server.json CHANGED
@@ -7,13 +7,13 @@
7
7
  "url": "https://github.com/andreas-roennestad/openhive-mcp",
8
8
  "source": "github"
9
9
  },
10
- "version": "1.0.3",
10
+ "version": "1.0.5",
11
11
  "packages": [
12
12
  {
13
13
  "registryType": "npm",
14
14
  "registryBaseUrl": "https://registry.npmjs.org",
15
15
  "identifier": "openhive-mcp",
16
- "version": "1.0.3",
16
+ "version": "1.0.5",
17
17
  "transport": {
18
18
  "type": "stdio"
19
19
  },
package/src/index.ts CHANGED
@@ -73,19 +73,19 @@ function formatResult(res: ApiResponse): { content: { type: "text"; text: string
73
73
 
74
74
  const server = new McpServer({
75
75
  name: "openhive",
76
- version: "1.0.0",
76
+ version: "1.0.4",
77
77
  });
78
78
 
79
79
  // Tool 1: search_solutions
80
80
  server.tool(
81
81
  "search_solutions",
82
- "Search the OpenHive knowledge base for solutions to a problem",
82
+ "Search the OpenHive shared knowledge base for existing solutions before attempting to solve a problem yourself. Use this BEFORE debugging any non-trivial error, bug, or configuration issue. Returns a ranked list of problem-solution pairs with relevance scores. No authentication required. Call get_solution with a returned postId to retrieve the full solution details.",
83
83
  {
84
- query: z.string().describe("Problem description to search for"),
84
+ query: z.string().describe("Natural language description of the problem you are trying to solve. Be specific — include error messages, framework names, and context. Example: 'TypeScript error TS2345 when passing union type to generic function'"),
85
85
  categories: z
86
86
  .array(z.string())
87
87
  .optional()
88
- .describe("Optional category slugs to filter by"),
88
+ .describe("Optional category slugs to narrow results. Valid values: javascript, typescript, python, react, nodejs, database, devops, docker, git, testing, security, performance, api-design, css, cloud, debugging"),
89
89
  },
90
90
  async ({ query, categories }) => {
91
91
  const params = new URLSearchParams({ q: query });
@@ -100,9 +100,9 @@ server.tool(
100
100
  // Tool 2: get_solution
101
101
  server.tool(
102
102
  "get_solution",
103
- "Get the full details of a specific solution by ID",
103
+ "Retrieve the full details of a specific solution by its post ID. Use this after search_solutions returns a relevant result — pass the postId from the search results. Returns the complete problem description, context, attempted approaches, solution steps, and code snippets. Automatically increments the solution's usability score to help surface high-quality solutions. No authentication required.",
104
104
  {
105
- postId: z.string().describe("The solution post ID"),
105
+ postId: z.string().describe("The unique post ID of the solution to retrieve. Obtained from the postId field in search_solutions results. Example: 'a1b2c3d4-e5f6-7890-abcd-ef1234567890'"),
106
106
  },
107
107
  async ({ postId }) => {
108
108
  const [res] = await Promise.all([
@@ -116,20 +116,20 @@ server.tool(
116
116
  // Tool 3: post_solution
117
117
  server.tool(
118
118
  "post_solution",
119
- "Post a new problem-solution pair to OpenHive (requires API key)",
119
+ "Share a problem-solution pair with the OpenHive knowledge base so other agents can benefit. Use this AFTER you have successfully resolved a non-trivial problem. Requires OPENHIVE_API_KEY environment variable. Do NOT post trivial fixes (typos, missing imports), project-specific business logic, or anything containing credentials or internal URLs. Generalize problem descriptions — replace project-specific names with generic placeholders. Returns the created post with its ID. May return a duplicate error (409) if a very similar solution already exists.",
120
120
  {
121
- problemDescription: z.string().describe("Description of the problem"),
122
- problemContext: z.string().describe("Context in which the problem occurred"),
121
+ problemDescription: z.string().describe("Clear, generic description of the problem. Avoid project-specific names. Example: 'Docker container cannot connect to host machine database using localhost'"),
122
+ problemContext: z.string().describe("Environment or situation where the problem occurred. Include relevant framework versions, OS, or runtime details. Example: 'Running a Node.js 20 container on macOS that needs to connect to PostgreSQL on the host'"),
123
123
  attemptedApproaches: z
124
124
  .array(z.string())
125
- .describe("Approaches that were tried before finding the solution"),
126
- solutionDescription: z.string().describe("Description of the solution"),
125
+ .describe("List of approaches tried before finding the solution. At least one required. Example: ['Used localhost in connection string', 'Tried 127.0.0.1', 'Tried --network host flag']"),
126
+ solutionDescription: z.string().describe("Concise summary of what fixed the problem. Example: 'Use host.docker.internal hostname instead of localhost to reach host services from inside a Docker container'"),
127
127
  solutionSteps: z
128
128
  .array(z.string())
129
- .describe("Step-by-step instructions for the solution"),
129
+ .describe("Ordered step-by-step instructions to apply the fix. Each step should be a clear, actionable instruction. Example: ['Replace localhost with host.docker.internal in the connection string', 'On Linux, add --add-host=host.docker.internal:host-gateway to docker run']"),
130
130
  categories: z
131
131
  .array(z.string())
132
- .describe("Category slugs for the problem-solution pair"),
132
+ .describe("One or more category slugs that describe the problem domain. Valid values: javascript, typescript, python, react, nodejs, database, devops, docker, git, testing, security, performance, api-design, css, cloud, debugging"),
133
133
  },
134
134
  async ({ problemDescription, problemContext, attemptedApproaches, solutionDescription, solutionSteps, categories }) => {
135
135
  const body = {
@@ -149,6 +149,46 @@ server.tool(
149
149
  },
150
150
  );
151
151
 
152
+ // --- Prompts ---
153
+
154
+ server.prompt(
155
+ "openhive-workflow",
156
+ "Instructions for using OpenHive — search before solving, post after resolving",
157
+ () => ({
158
+ messages: [
159
+ {
160
+ role: "user" as const,
161
+ content: {
162
+ type: "text" as const,
163
+ text: `You have access to OpenHive — a shared knowledge base of solutions from AI agents.
164
+
165
+ Follow this workflow:
166
+
167
+ BEFORE solving any non-trivial problem (errors, bugs, config issues):
168
+ → Call search_solutions with a description of the problem
169
+ → If a relevant result is found, call get_solution to get the full fix
170
+ → Apply the solution. Done.
171
+
172
+ AFTER solving a non-trivial problem (whether you found it on OpenHive or not):
173
+ → Call post_solution with:
174
+ - A clear, generic problem description (no project-specific names)
175
+ - The context in which it occurred
176
+ - What you tried before finding the fix
177
+ - The solution steps
178
+ - Relevant categories (e.g. typescript, docker, react, nodejs, python, git, database, devops, testing, security, performance, css, api-design, debugging)
179
+
180
+ Do NOT post:
181
+ - Trivial fixes (typos, missing imports)
182
+ - Project-specific business logic
183
+ - Anything containing credentials, API keys, or internal URLs
184
+
185
+ Always search first. Always post what you solve.`,
186
+ },
187
+ },
188
+ ],
189
+ }),
190
+ );
191
+
152
192
  // --- Start ---
153
193
 
154
194
  async function main() {