@nooticr/mcp 1.26.74 → 1.26.76
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/dist/auth.js +25 -7
- package/dist/index.js +8 -13
- package/dist/shared/tools.js +1 -1
- package/dist/shared/ui-template.js +10 -4
- package/package.json +1 -1
package/dist/auth.js
CHANGED
|
@@ -225,17 +225,35 @@ export function createManagementTokenProvider(auth) {
|
|
|
225
225
|
/**
|
|
226
226
|
* Builds a TokenProvider for one caller's own API key — the headless path
|
|
227
227
|
* through HTTP mode, where the bearer the client presented *is* the nooticr
|
|
228
|
-
* credential.
|
|
229
|
-
*
|
|
230
|
-
* tenant's call with another's account.
|
|
228
|
+
* credential. Never the operator's environment or credentials file, which would
|
|
229
|
+
* answer one tenant's call with another's account.
|
|
231
230
|
*/
|
|
232
231
|
export function createApiKeyTokenProvider(apiKey) {
|
|
233
232
|
return { getAccessToken: async () => apiKey };
|
|
234
233
|
}
|
|
235
|
-
/**
|
|
236
|
-
|
|
234
|
+
/**
|
|
235
|
+
* Builds a TokenProvider for one OAuth session in HTTP mode: that session's
|
|
236
|
+
* nooticr tokens and nothing else. The environment and the credentials file
|
|
237
|
+
* belong to whoever runs the server; resolving them here answered every
|
|
238
|
+
* signed-in user as the operator. A refresh updates the session in place, so
|
|
239
|
+
* the next request from the same login carries the new token, and nothing is
|
|
240
|
+
* written to the operator's credentials file.
|
|
241
|
+
*/
|
|
242
|
+
export function createSessionTokenProvider(baseUrl, session) {
|
|
237
243
|
return {
|
|
238
|
-
getAccessToken: async () =>
|
|
239
|
-
onUnauthorized: async () =>
|
|
244
|
+
getAccessToken: async () => session.nooticrAccessToken || undefined,
|
|
245
|
+
onUnauthorized: async () => {
|
|
246
|
+
if (!session.nooticrRefreshToken)
|
|
247
|
+
return false;
|
|
248
|
+
try {
|
|
249
|
+
const next = await NooticrClient.refreshSession(baseUrl, session.nooticrRefreshToken);
|
|
250
|
+
session.nooticrAccessToken = next.accessToken;
|
|
251
|
+
session.nooticrRefreshToken = next.refreshToken ?? session.nooticrRefreshToken;
|
|
252
|
+
return true;
|
|
253
|
+
}
|
|
254
|
+
catch {
|
|
255
|
+
return false;
|
|
256
|
+
}
|
|
257
|
+
},
|
|
240
258
|
};
|
|
241
259
|
}
|
package/dist/index.js
CHANGED
|
@@ -14,7 +14,7 @@ import { randomUUID } from "node:crypto";
|
|
|
14
14
|
import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js";
|
|
15
15
|
import { StreamableHTTPServerTransport } from "@modelcontextprotocol/sdk/server/streamableHttp.js";
|
|
16
16
|
import { getBaseUrl, getPublicUrl, getPort, getCredentialsFile, getTransportMode, DEFAULT_PORT, } from "./config.js";
|
|
17
|
-
import { AuthManager, NooticrAuthError, createApiKeyTokenProvider,
|
|
17
|
+
import { AuthManager, NooticrAuthError, createApiKeyTokenProvider, createSessionTokenProvider, createManagementTokenProvider, createStdioTokenProvider, } from "./auth.js";
|
|
18
18
|
import { forwardedHeaders, forwardedSession, looksLikeApiKey } from "./shared/api-key.js";
|
|
19
19
|
import { NooticrClient, NooticrError } from "./nooticr.js";
|
|
20
20
|
import { OAuthManager, SCOPES } from "./oauth.js";
|
|
@@ -227,9 +227,6 @@ export async function runHttp(port, publicUrl) {
|
|
|
227
227
|
client: new NooticrClient(baseUrl, {
|
|
228
228
|
getAccessToken: async () => undefined,
|
|
229
229
|
}),
|
|
230
|
-
onSession: async (session) => {
|
|
231
|
-
await auth.persistSession(session);
|
|
232
|
-
},
|
|
233
230
|
});
|
|
234
231
|
const state = {
|
|
235
232
|
oauth,
|
|
@@ -239,9 +236,9 @@ export async function runHttp(port, publicUrl) {
|
|
|
239
236
|
serverFactory: () => createMcpServer((extra) => {
|
|
240
237
|
const bearer = extra.authInfo?.token;
|
|
241
238
|
// A caller who presented their own API key is answered as themselves.
|
|
242
|
-
//
|
|
243
|
-
//
|
|
244
|
-
//
|
|
239
|
+
// No branch below falls back to the *operator's* environment or
|
|
240
|
+
// credentials file: that would serve one tenant's request from
|
|
241
|
+
// another's account.
|
|
245
242
|
if (looksLikeApiKey(bearer)) {
|
|
246
243
|
return new NooticrClient(baseUrl, createApiKeyTokenProvider(bearer));
|
|
247
244
|
}
|
|
@@ -250,15 +247,13 @@ export async function runHttp(port, publicUrl) {
|
|
|
250
247
|
if (forwarded) {
|
|
251
248
|
return new NooticrClient(baseUrl, createApiKeyTokenProvider(forwarded.token), undefined, forwardedHeaders(forwarded));
|
|
252
249
|
}
|
|
250
|
+
// An OAuth login of this server: only that session's own tokens.
|
|
253
251
|
const session = bearer
|
|
254
252
|
? oauth.verifyToken(bearer)
|
|
255
253
|
: undefined;
|
|
256
|
-
return new NooticrClient(baseUrl,
|
|
257
|
-
?
|
|
258
|
-
|
|
259
|
-
refreshToken: session.nooticrRefreshToken,
|
|
260
|
-
}
|
|
261
|
-
: undefined));
|
|
254
|
+
return new NooticrClient(baseUrl, session
|
|
255
|
+
? createSessionTokenProvider(baseUrl, session)
|
|
256
|
+
: { getAccessToken: async () => undefined });
|
|
262
257
|
}),
|
|
263
258
|
};
|
|
264
259
|
const server = http.createServer((req, res) => {
|
package/dist/shared/tools.js
CHANGED
|
@@ -36,7 +36,7 @@ import { registerAmazonTools } from "./amazon.js";
|
|
|
36
36
|
import { registerMarketplaceTools } from "./marketplace.js";
|
|
37
37
|
import { DEFAULT_NOOTICR_SETTINGS, DEFAULT_SOCIAL_PLATFORMS, MemorySettingsStore, SETTINGS_READ_TOOL, SETTINGS_UPDATE_TOOL, settingsOwnerFromAuth, } from "./settings.js";
|
|
38
38
|
/** Current MCP server version — bumped on every deploy for traceability. */
|
|
39
|
-
export const MCP_SERVER_VERSION = "1.26.
|
|
39
|
+
export const MCP_SERVER_VERSION = "1.26.76";
|
|
40
40
|
/** MCP Apps extension identifier */
|
|
41
41
|
const UI_EXTENSION = "io.modelcontextprotocol/ui";
|
|
42
42
|
/** MIME type for MCP Apps HTML resources */
|
|
@@ -2066,7 +2066,8 @@ export const NOOTICR_UI_TEMPLATE = `<!DOCTYPE html>
|
|
|
2066
2066
|
var GROUP_PEEK=4;
|
|
2067
2067
|
/** Groups the reader has opened, by post URL, kept across a filter or sort. */
|
|
2068
2068
|
var expandedGroups={};
|
|
2069
|
-
//
|
|
2069
|
+
// The poster the reader asked to play, keyed like expandedGroups. At most
|
|
2070
|
+
// one key: see the [data-mplay] handler.
|
|
2070
2071
|
var expandedMedia={};
|
|
2071
2072
|
|
|
2072
2073
|
/** Reach of the post a comment sits under — how many people saw it. */
|
|
@@ -2227,11 +2228,16 @@ export const NOOTICR_UI_TEMPLATE = `<!DOCTYPE html>
|
|
|
2227
2228
|
if(mplay&&(monitorState||spokenState)){
|
|
2228
2229
|
var mkey=mplay.getAttribute("data-mplay")||"";
|
|
2229
2230
|
if(mkey&&mplay.className.indexOf("is-playable")>=0){
|
|
2231
|
+
// One post plays at a time. Every expanded stage is redrawn with
|
|
2232
|
+
// autoplay, so a second poster click used to restart the first video
|
|
2233
|
+
// under the new one, and only the first stage in the page was
|
|
2234
|
+
// registered below, so neither paused the other (#253).
|
|
2235
|
+
expandedMedia={};
|
|
2230
2236
|
expandedMedia[mkey]=true;
|
|
2231
2237
|
renderMentions();
|
|
2232
|
-
//
|
|
2233
|
-
//
|
|
2234
|
-
//
|
|
2238
|
+
// Nothing in a mention view is a bound player today (no .mp, .au or
|
|
2239
|
+
// poster fallback), so this only resets the registries before the
|
|
2240
|
+
// stage is registered; it binds anything a later view adds.
|
|
2235
2241
|
initPlayers();
|
|
2236
2242
|
var v=document.querySelector(".mgroup-stage video");
|
|
2237
2243
|
if(v){registerAudio(v);stopAllPlayers();}
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@nooticr/mcp",
|
|
3
3
|
"mcpName": "com.nooticr/mcp",
|
|
4
|
-
"version": "1.26.
|
|
4
|
+
"version": "1.26.76",
|
|
5
5
|
"description": "MCP server for nooticr - fetch, discover and understand TikTok/Instagram/YouTube/X/Reddit/LinkedIn/Weibo posts with AI (media metadata, niche discovery, brand monitoring, hook & viral analysis)",
|
|
6
6
|
"homepage": "https://mcp.nooticr.com",
|
|
7
7
|
"repository": {
|