clickshot-mcp 0.1.0 → 0.1.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.
Files changed (2) hide show
  1. package/package.json +1 -1
  2. package/server.js +32 -6
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "clickshot-mcp",
3
- "version": "0.1.0",
3
+ "version": "0.1.1",
4
4
  "description": "Local MCP server that feeds ClickShot screenshots into your running Claude (Code/Desktop) on your own subscription.",
5
5
  "type": "module",
6
6
  "bin": {
package/server.js CHANGED
@@ -18,7 +18,7 @@ import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
18
18
  import { StreamableHTTPServerTransport } from "@modelcontextprotocol/sdk/server/streamableHttp.js";
19
19
  import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js";
20
20
 
21
- const VERSION = "0.1.0";
21
+ const VERSION = "0.1.1";
22
22
 
23
23
  // stdout is the JSON-RPC channel in stdio mode, so all logging goes to stderr.
24
24
  const log = (...a) => console.error(...a);
@@ -154,13 +154,31 @@ function buildIngestApp() {
154
154
  // ---------------------------------------------------------------------------
155
155
  // Boot
156
156
  // ---------------------------------------------------------------------------
157
+ // Bind the ingest port without letting a conflict crash the process.
158
+ function listenIngest(app, { fatalOnError }) {
159
+ const srv = app.listen(PORT, "127.0.0.1", () => {
160
+ log(`ClickShot ingest on http://127.0.0.1:${PORT}/capture`);
161
+ });
162
+ srv.on("error", (err) => {
163
+ if (err && err.code === "EADDRINUSE") {
164
+ if (fatalOnError) {
165
+ log(`Port ${PORT} is already in use — another ClickShot server is running. Stop it, or set CLICKSHOT_PORT to a free port.`);
166
+ process.exit(1);
167
+ }
168
+ log(`Port ${PORT} already in use — another ClickShot server is handling ingest. Continuing with MCP over stdio.`);
169
+ } else {
170
+ log("Ingest server error:", err && err.message ? err.message : err);
171
+ if (fatalOnError) process.exit(1);
172
+ }
173
+ });
174
+ return srv;
175
+ }
176
+
157
177
  async function main() {
158
178
  if (STDIO) {
159
179
  // Claude Desktop launches this; talk MCP over stdio, ingest over HTTP.
160
- const app = buildIngestApp();
161
- app.listen(PORT, "127.0.0.1", () => {
162
- log(`ClickShot ingest on http://127.0.0.1:${PORT}/capture (stdio MCP mode)`);
163
- });
180
+ // A port conflict must NOT kill the MCP connection.
181
+ listenIngest(buildIngestApp(), { fatalOnError: false });
164
182
  const server = buildMcpServer();
165
183
  const transport = new StdioServerTransport();
166
184
  await server.connect(transport);
@@ -191,13 +209,21 @@ async function main() {
191
209
  app.get("/mcp", methodNotAllowed);
192
210
  app.delete("/mcp", methodNotAllowed);
193
211
 
194
- app.listen(PORT, "127.0.0.1", () => {
212
+ const srv = app.listen(PORT, "127.0.0.1", () => {
195
213
  log(`ClickShot MCP server on http://127.0.0.1:${PORT}`);
196
214
  log(` • extension ingest: POST http://127.0.0.1:${PORT}/capture`);
197
215
  log(` • MCP endpoint: http://127.0.0.1:${PORT}/mcp`);
198
216
  log(`Register in Claude Code:`);
199
217
  log(` claude mcp add --transport http clickshot http://127.0.0.1:${PORT}/mcp`);
200
218
  });
219
+ srv.on("error", (err) => {
220
+ if (err && err.code === "EADDRINUSE") {
221
+ log(`Port ${PORT} is already in use — another ClickShot server is running. Stop it, or set CLICKSHOT_PORT to a free port.`);
222
+ } else {
223
+ log("Server error:", err && err.message ? err.message : err);
224
+ }
225
+ process.exit(1);
226
+ });
201
227
  }
202
228
  }
203
229