omnipost-mcp 0.1.0 → 0.1.2
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 +1 -1
- package/src/bridge.js +18 -4
- package/src/index.js +9 -5
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "omnipost-mcp",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.2",
|
|
4
4
|
"description": "MCP server for OmniPost: lets Claude Code, Claude Desktop, Cursor and other MCP clients publish articles, image posts and videos to 40+ Chinese and overseas platforms through the OmniPost desktop app running on your machine.",
|
|
5
5
|
"mcpName": "io.github.OmniGoAI/omnipost",
|
|
6
6
|
"type": "module",
|
package/src/bridge.js
CHANGED
|
@@ -21,6 +21,11 @@ export const DOWNLOAD_URL = 'https://omnigoai.com/en/download/omnipost/';
|
|
|
21
21
|
// and retry it, uploading the same content twice.
|
|
22
22
|
export const CALL_TIMEOUT_MS = 6 * 3600 * 1000;
|
|
23
23
|
|
|
24
|
+
// Number of tool calls currently in progress. The process waits for these before exiting, so a
|
|
25
|
+
// client that closes stdin right after sending a request still gets its answer.
|
|
26
|
+
let inFlightCalls = 0;
|
|
27
|
+
export const inFlight = () => inFlightCalls;
|
|
28
|
+
|
|
24
29
|
// Node's built-in fetch drops a response body that stays idle for 5 minutes. The app's SSE stream
|
|
25
30
|
// is silent while a long publish is running, so use a dispatcher without body/header timeouts.
|
|
26
31
|
const longLivedAgent = new Agent({ bodyTimeout: 0, headersTimeout: 0, keepAliveTimeout: 60_000 });
|
|
@@ -81,7 +86,7 @@ export class AppConnection {
|
|
|
81
86
|
async get() {
|
|
82
87
|
if (this.client) return this.client;
|
|
83
88
|
const endpoint = this.resolve();
|
|
84
|
-
const client = new Client({ name: 'omnipost-mcp-bridge', version: '0.1.
|
|
89
|
+
const client = new Client({ name: 'omnipost-mcp-bridge', version: '0.1.2' });
|
|
85
90
|
client.onclose = () => { if (this.client === client) this.client = null; };
|
|
86
91
|
const connecting = client.connect(this.transportFactory(endpoint));
|
|
87
92
|
let timer;
|
|
@@ -112,7 +117,7 @@ function shortCause(err) {
|
|
|
112
117
|
return String(err?.cause?.code || err?.code || err?.message || err).slice(0, 160);
|
|
113
118
|
}
|
|
114
119
|
|
|
115
|
-
export function createBridgeServer({ connection = new AppConnection(), snapshot = loadSnapshot(), version = '0.1.
|
|
120
|
+
export function createBridgeServer({ connection = new AppConnection(), snapshot = loadSnapshot(), version = '0.1.2' } = {}) {
|
|
116
121
|
const server = new Server(
|
|
117
122
|
{ name: 'omnipost', version },
|
|
118
123
|
{
|
|
@@ -136,6 +141,15 @@ export function createBridgeServer({ connection = new AppConnection(), snapshot
|
|
|
136
141
|
});
|
|
137
142
|
|
|
138
143
|
server.setRequestHandler(CallToolRequestSchema, async (request) => {
|
|
144
|
+
inFlightCalls += 1;
|
|
145
|
+
try {
|
|
146
|
+
return await handleCall(request);
|
|
147
|
+
} finally {
|
|
148
|
+
inFlightCalls -= 1;
|
|
149
|
+
}
|
|
150
|
+
});
|
|
151
|
+
|
|
152
|
+
async function handleCall(request) {
|
|
139
153
|
const { name, arguments: args } = request.params;
|
|
140
154
|
let client;
|
|
141
155
|
try {
|
|
@@ -162,10 +176,10 @@ export function createBridgeServer({ connection = new AppConnection(), snapshot
|
|
|
162
176
|
isError: true,
|
|
163
177
|
};
|
|
164
178
|
}
|
|
165
|
-
}
|
|
179
|
+
}
|
|
166
180
|
|
|
167
181
|
// When the AI client goes away, drop the link to the app too, so nothing is left open.
|
|
168
|
-
server.onclose = () => { connection.reset(); };
|
|
182
|
+
server.onclose = () => { if (inFlightCalls === 0) connection.reset(); };
|
|
169
183
|
|
|
170
184
|
return server;
|
|
171
185
|
}
|
package/src/index.js
CHANGED
|
@@ -3,12 +3,16 @@
|
|
|
3
3
|
// Claude Code: claude mcp add omnipost -- npx -y omnipost-mcp
|
|
4
4
|
// Other clients: { "command": "npx", "args": ["-y", "omnipost-mcp"] }
|
|
5
5
|
import { StdioServerTransport } from '@modelcontextprotocol/sdk/server/stdio.js';
|
|
6
|
-
import { createBridgeServer, resolveEndpoint, shutdown } from './bridge.js';
|
|
6
|
+
import { createBridgeServer, resolveEndpoint, shutdown, inFlight } from './bridge.js';
|
|
7
7
|
|
|
8
8
|
let exiting = false;
|
|
9
|
-
async function exit(code = 0) {
|
|
9
|
+
async function exit(code = 0, { immediate = false } = {}) {
|
|
10
10
|
if (exiting) return;
|
|
11
11
|
exiting = true;
|
|
12
|
+
// Let calls that are already running finish and send their answers first. The short pause lets a
|
|
13
|
+
// request that arrived just before stdin closed get registered as in flight.
|
|
14
|
+
if (!immediate) await new Promise((r) => setTimeout(r, 300));
|
|
15
|
+
while (!immediate && inFlight() > 0) await new Promise((r) => setTimeout(r, 200));
|
|
12
16
|
await shutdown();
|
|
13
17
|
process.exit(code);
|
|
14
18
|
}
|
|
@@ -22,12 +26,12 @@ async function main() {
|
|
|
22
26
|
// The client closing our stdin means it is done with us.
|
|
23
27
|
process.stdin.on('end', () => exit(0));
|
|
24
28
|
process.stdin.on('close', () => exit(0));
|
|
25
|
-
process.on('SIGINT', () => exit(0));
|
|
26
|
-
process.on('SIGTERM', () => exit(0));
|
|
29
|
+
process.on('SIGINT', () => exit(0, { immediate: true }));
|
|
30
|
+
process.on('SIGTERM', () => exit(0, { immediate: true }));
|
|
27
31
|
process.stderr.write(`[omnipost-mcp] ready, forwarding to ${resolveEndpoint()}\n`);
|
|
28
32
|
}
|
|
29
33
|
|
|
30
34
|
main().catch((err) => {
|
|
31
35
|
process.stderr.write(`[omnipost-mcp] failed to start: ${err?.stack || err}\n`);
|
|
32
|
-
exit(1);
|
|
36
|
+
exit(1, { immediate: true });
|
|
33
37
|
});
|