@neopress/mcp 1.5.0 → 1.6.0

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/index.js CHANGED
@@ -173,6 +173,10 @@ var EntriesEndpoint = class {
173
173
  collectionId
174
174
  })).data;
175
175
  }
176
+ /** Copy source content into a linked locale draft, or return its existing translation. */
177
+ async createTranslation(entryId, locale) {
178
+ return (await this.client.post(`${this.basePath}/${entryId}/translations`, { locale })).data;
179
+ }
176
180
  async update(entryId, data) {
177
181
  const payload = {};
178
182
  for (const key of UPDATE_PASSTHROUGH_FIELDS) if (key in data) payload[key] = data[key];
@@ -450,8 +454,12 @@ function appendCommonAnalyticsParams(qs, params) {
450
454
  }
451
455
  var AnalyticsEndpoint = class {
452
456
  client;
457
+ events;
458
+ funnels;
453
459
  constructor(client) {
454
460
  this.client = client;
461
+ this.events = new AnalyticsEventsEndpoint(client);
462
+ this.funnels = new AnalyticsFunnelsEndpoint(client);
455
463
  }
456
464
  get basePath() {
457
465
  return `${this.client.siteBasePath}/analytics`;
@@ -508,6 +516,58 @@ var AnalyticsEndpoint = class {
508
516
  if (params.rowLimit) qs.set("row_limit", String(params.rowLimit));
509
517
  return (await this.client.get(`${this.basePath}/search-console?${qs.toString()}`)).data;
510
518
  }
519
+ /** Page/form targets that can be referenced by an event definition. */
520
+ async targets() {
521
+ return (await this.client.get(`${this.basePath}/targets`)).data;
522
+ }
523
+ };
524
+ var AnalyticsEventsEndpoint = class {
525
+ client;
526
+ constructor(client) {
527
+ this.client = client;
528
+ }
529
+ get basePath() {
530
+ return `${this.client.siteBasePath}/analytics/events`;
531
+ }
532
+ async list() {
533
+ return (await this.client.get(this.basePath)).data;
534
+ }
535
+ async get(eventId) {
536
+ return (await this.client.get(`${this.basePath}/${eventId}`)).data.event;
537
+ }
538
+ async create(data) {
539
+ return (await this.client.post(this.basePath, data)).data.event;
540
+ }
541
+ async update(eventId, data) {
542
+ return (await this.client.patch(`${this.basePath}/${eventId}`, data)).data.event;
543
+ }
544
+ async delete(eventId) {
545
+ await this.client.delete(`${this.basePath}/${eventId}`);
546
+ }
547
+ };
548
+ var AnalyticsFunnelsEndpoint = class {
549
+ client;
550
+ constructor(client) {
551
+ this.client = client;
552
+ }
553
+ get basePath() {
554
+ return `${this.client.siteBasePath}/analytics/funnels`;
555
+ }
556
+ async list() {
557
+ return (await this.client.get(this.basePath)).data;
558
+ }
559
+ async get(funnelId) {
560
+ return (await this.client.get(`${this.basePath}/${funnelId}`)).data.funnel;
561
+ }
562
+ async create(data) {
563
+ return (await this.client.post(this.basePath, data)).data.funnel;
564
+ }
565
+ async update(funnelId, data) {
566
+ return (await this.client.patch(`${this.basePath}/${funnelId}`, data)).data.funnel;
567
+ }
568
+ async delete(funnelId) {
569
+ await this.client.delete(`${this.basePath}/${funnelId}`);
570
+ }
511
571
  };
512
572
  //#endregion
513
573
  //#region ../sdk/src/endpoints/templates.ts
@@ -1233,6 +1293,11 @@ const READ_ONLY_TOOLS = /* @__PURE__ */ new Set([
1233
1293
  "neopress_analytics_traffic_sources",
1234
1294
  "neopress_analytics_forms",
1235
1295
  "neopress_analytics_crawler_summary",
1296
+ "neopress_analytics_events_list",
1297
+ "neopress_analytics_event_get",
1298
+ "neopress_analytics_funnels_list",
1299
+ "neopress_analytics_funnel_get",
1300
+ "neopress_analytics_targets_list",
1236
1301
  "neopress_search_console_query",
1237
1302
  "neopress_assets_list",
1238
1303
  "neopress_asset_get",
@@ -1256,7 +1321,13 @@ const DESTRUCTIVE_TOOLS = /* @__PURE__ */ new Set([
1256
1321
  "neopress_form_delete",
1257
1322
  "neopress_asset_delete",
1258
1323
  "neopress_template_mark",
1259
- "neopress_publish_site"
1324
+ "neopress_publish_site",
1325
+ "neopress_analytics_event_create",
1326
+ "neopress_analytics_event_update",
1327
+ "neopress_analytics_event_delete",
1328
+ "neopress_analytics_funnel_create",
1329
+ "neopress_analytics_funnel_update",
1330
+ "neopress_analytics_funnel_delete"
1260
1331
  ]);
1261
1332
  const PUBLICATION_TOOLS = /* @__PURE__ */ new Set([
1262
1333
  "neopress_entry_publish",
@@ -1297,6 +1368,12 @@ function asOptionalNumber(input, key) {
1297
1368
  function asOptionalString(input, key) {
1298
1369
  return input[key];
1299
1370
  }
1371
+ function asOptionalBoolean(input, key) {
1372
+ return input[key];
1373
+ }
1374
+ function omitUndefined(value) {
1375
+ return Object.fromEntries(Object.entries(value).filter(([, item]) => item !== void 0));
1376
+ }
1300
1377
  function siteId(input) {
1301
1378
  return asOptionalNumber(input, "siteId");
1302
1379
  }
@@ -1523,10 +1600,11 @@ const toolDefinitions = [
1523
1600
  title: z.string().optional(),
1524
1601
  type: z.enum(["static", "dynamic"]).optional(),
1525
1602
  status: z.enum(["draft", "published"]).optional(),
1603
+ visibility: z.enum(["public", "hidden"]).optional(),
1526
1604
  collectionId: z.number().int().positive().optional(),
1527
1605
  draftTsx: z.string().optional(),
1528
1606
  draftI18n: optionalJsonSchema,
1529
- draftPublicLocales: z.array(z.string()).nullable().optional(),
1607
+ draftPublicLocales: z.array(z.string()).nullable().optional().describe("Draft public languages. null means default language only; [] means none. Publish to apply."),
1530
1608
  draftMeta: optionalJsonSchema,
1531
1609
  queryConfig: optionalJsonSchema,
1532
1610
  metadata: optionalJsonSchema
@@ -1537,6 +1615,7 @@ const toolDefinitions = [
1537
1615
  title: asOptionalString(input, "title"),
1538
1616
  type: input.type,
1539
1617
  status: input.status,
1618
+ visibility: input.visibility,
1540
1619
  collectionId: asOptionalNumber(input, "collectionId"),
1541
1620
  draftTsx: asOptionalString(input, "draftTsx"),
1542
1621
  draftI18n: input.draftI18n,
@@ -1557,27 +1636,29 @@ const toolDefinitions = [
1557
1636
  title: z.string().optional(),
1558
1637
  type: z.enum(["static", "dynamic"]).optional(),
1559
1638
  status: z.string().optional(),
1639
+ visibility: z.enum(["public", "hidden"]).optional(),
1560
1640
  collectionId: z.number().int().positive().optional(),
1561
1641
  draftTsx: z.string().optional(),
1562
1642
  draftI18n: optionalJsonSchema,
1563
- draftPublicLocales: z.array(z.string()).nullable().optional(),
1643
+ draftPublicLocales: z.array(z.string()).nullable().optional().describe("Draft public languages. null means default language only; [] means none. Publish to apply."),
1564
1644
  draftMeta: optionalJsonSchema,
1565
1645
  queryConfig: optionalJsonSchema,
1566
1646
  metadata: optionalJsonSchema
1567
1647
  },
1568
1648
  handler: async (input, context, extra) => {
1569
- return (await context.createClient({ siteId: siteId(input) }, extra)).pages.update(asNumber(input, "pageId"), {
1649
+ return (await context.createClient({ siteId: siteId(input) }, extra)).pages.update(asNumber(input, "pageId"), omitUndefined({
1570
1650
  path: asOptionalString(input, "path"),
1571
1651
  title: asOptionalString(input, "title"),
1572
1652
  type: asOptionalString(input, "type"),
1573
1653
  status: asOptionalString(input, "status"),
1654
+ visibility: input.visibility,
1574
1655
  collectionId: asOptionalNumber(input, "collectionId"),
1575
1656
  draftTsx: asOptionalString(input, "draftTsx"),
1576
1657
  draftI18n: input.draftI18n,
1577
1658
  draftPublicLocales: input.draftPublicLocales,
1578
1659
  draftMeta: mergeDraftMeta(input.draftMeta, input.queryConfig),
1579
1660
  metadata: input.metadata
1580
- });
1661
+ }));
1581
1662
  }
1582
1663
  },
1583
1664
  {
@@ -1733,6 +1814,19 @@ const toolDefinitions = [
1733
1814
  return entry;
1734
1815
  }
1735
1816
  },
1817
+ {
1818
+ name: "neopress_entry_create_translation",
1819
+ title: "Create Entry Translation Draft",
1820
+ description: "Create or return a linked locale row in the source entry's translation group. New drafts copy source content; translate the returned entry with entry_update, then publish it. Existing translations are preserved.",
1821
+ inputSchema: {
1822
+ ...siteIdShape,
1823
+ entryId: z.number().int().positive(),
1824
+ locale: z.string().min(1)
1825
+ },
1826
+ handler: async (input, context, extra) => {
1827
+ return (await context.createClient({ siteId: siteId(input) }, extra)).entries.createTranslation(asNumber(input, "entryId"), asString(input, "locale"));
1828
+ }
1829
+ },
1736
1830
  {
1737
1831
  name: "neopress_entry_update",
1738
1832
  title: "Update Entry",
@@ -1749,14 +1843,14 @@ const toolDefinitions = [
1749
1843
  },
1750
1844
  handler: async (input, context, extra) => {
1751
1845
  const client = await context.createClient({ siteId: siteId(input) }, extra);
1752
- const entry = await client.entries.update(asNumber(input, "entryId"), {
1846
+ const entry = await client.entries.update(asNumber(input, "entryId"), omitUndefined({
1753
1847
  slug: asOptionalString(input, "slug"),
1754
1848
  title: asOptionalString(input, "title"),
1755
1849
  locale: asOptionalString(input, "locale"),
1756
1850
  data: input.data,
1757
1851
  metadata: input.metadata,
1758
1852
  status: asOptionalString(input, "status")
1759
- });
1853
+ }));
1760
1854
  await client.entries.revalidateReaderCache(asNumber(input, "entryId"));
1761
1855
  return entry;
1762
1856
  }
@@ -1921,14 +2015,14 @@ const toolDefinitions = [
1921
2015
  settings: optionalJsonSchema
1922
2016
  },
1923
2017
  handler: async (input, context, extra) => {
1924
- return (await context.createClient({ siteId: siteId(input) }, extra)).forms.update(asNumber(input, "formId"), {
2018
+ return (await context.createClient({ siteId: siteId(input) }, extra)).forms.update(asNumber(input, "formId"), omitUndefined({
1925
2019
  name: asOptionalString(input, "name"),
1926
- draftSchema: input.draftSchema ?? input.schema,
2020
+ draftSchema: input.draftSchema !== void 0 ? input.draftSchema : input.schema,
1927
2021
  draftLayout: input.draftLayout,
1928
2022
  draftStyle: input.draftStyle,
1929
2023
  draftI18n: input.draftI18n,
1930
2024
  settings: input.settings
1931
- });
2025
+ }));
1932
2026
  }
1933
2027
  },
1934
2028
  {
@@ -1972,6 +2066,235 @@ const toolDefinitions = [
1972
2066
  });
1973
2067
  }
1974
2068
  },
2069
+ {
2070
+ name: "neopress_analytics_events_list",
2071
+ title: "List Analytics Events",
2072
+ description: "List saved analytics event definitions for the active site.",
2073
+ inputSchema: siteIdShape,
2074
+ handler: async (input, context, extra) => {
2075
+ return (await context.createClient({ siteId: siteId(input) }, extra)).analytics.events.list();
2076
+ }
2077
+ },
2078
+ {
2079
+ name: "neopress_analytics_event_get",
2080
+ title: "Get Analytics Event",
2081
+ description: "Get a saved analytics event definition by UUID.",
2082
+ inputSchema: {
2083
+ ...siteIdShape,
2084
+ eventId: z.string().uuid()
2085
+ },
2086
+ handler: async (input, context, extra) => {
2087
+ return (await context.createClient({ siteId: siteId(input) }, extra)).analytics.events.get(asString(input, "eventId"));
2088
+ }
2089
+ },
2090
+ {
2091
+ name: "neopress_analytics_event_create",
2092
+ title: "Create Analytics Event",
2093
+ description: "Create a saved analytics event definition. Discover pages/forms with neopress_analytics_targets_list. Click/visibility require an existing stable [data-np-track=\"...\"] selector; page views reuse PAGE_VIEW. Optional id is a client UUID: reuse the same id and payload after an uncertain response.",
2094
+ inputSchema: {
2095
+ ...siteIdShape,
2096
+ id: z.string().uuid().optional(),
2097
+ name: z.string(),
2098
+ eventType: z.enum([
2099
+ "custom",
2100
+ "page",
2101
+ "click",
2102
+ "form",
2103
+ "scroll",
2104
+ "visibility",
2105
+ "dwell"
2106
+ ]),
2107
+ eventName: z.string().optional(),
2108
+ path: z.string().optional(),
2109
+ selector: z.string().optional(),
2110
+ formId: z.string().optional(),
2111
+ scrollDepth: z.number().int().optional(),
2112
+ dwellSeconds: z.number().int().optional()
2113
+ },
2114
+ handler: async (input, context, extra) => {
2115
+ return (await context.createClient({ siteId: siteId(input) }, extra)).analytics.events.create({
2116
+ id: asOptionalString(input, "id"),
2117
+ name: asString(input, "name"),
2118
+ eventType: input.eventType,
2119
+ eventName: asOptionalString(input, "eventName"),
2120
+ path: asOptionalString(input, "path"),
2121
+ selector: asOptionalString(input, "selector"),
2122
+ formId: asOptionalString(input, "formId"),
2123
+ scrollDepth: asOptionalNumber(input, "scrollDepth"),
2124
+ dwellSeconds: asOptionalNumber(input, "dwellSeconds")
2125
+ });
2126
+ }
2127
+ },
2128
+ {
2129
+ name: "neopress_analytics_event_update",
2130
+ title: "Update Analytics Event",
2131
+ description: "Rename an analytics event with {name} while preserving tracking behavior, or update its display settings separately. Tracking identity cannot be changed after creation.",
2132
+ inputSchema: {
2133
+ ...siteIdShape,
2134
+ eventId: z.string().uuid(),
2135
+ name: z.string().optional(),
2136
+ eventType: z.enum([
2137
+ "custom",
2138
+ "page",
2139
+ "click",
2140
+ "form",
2141
+ "scroll",
2142
+ "visibility",
2143
+ "dwell"
2144
+ ]).optional(),
2145
+ eventName: z.string().optional(),
2146
+ path: z.string().optional(),
2147
+ selector: z.string().optional(),
2148
+ formId: z.string().optional(),
2149
+ scrollDepth: z.number().int().optional(),
2150
+ dwellSeconds: z.number().int().optional(),
2151
+ chartVisible: z.boolean().optional(),
2152
+ pinned: z.boolean().optional(),
2153
+ chartColor: z.string().optional()
2154
+ },
2155
+ handler: async (input, context, extra) => {
2156
+ const client = await context.createClient({ siteId: siteId(input) }, extra);
2157
+ if ([
2158
+ "chartVisible",
2159
+ "pinned",
2160
+ "chartColor"
2161
+ ].some((key) => key in input)) {
2162
+ if ([
2163
+ "name",
2164
+ "eventType",
2165
+ "eventName",
2166
+ "path",
2167
+ "selector",
2168
+ "formId",
2169
+ "scrollDepth",
2170
+ "dwellSeconds"
2171
+ ].some((key) => input[key] !== void 0)) throw new Error("Update the definition and display settings in separate calls.");
2172
+ return client.analytics.events.update(asString(input, "eventId"), { display: {
2173
+ chartVisible: asOptionalBoolean(input, "chartVisible"),
2174
+ pinned: asOptionalBoolean(input, "pinned"),
2175
+ chartColor: asOptionalString(input, "chartColor")
2176
+ } });
2177
+ }
2178
+ const definition = {
2179
+ name: asString(input, "name"),
2180
+ ...input.eventType !== void 0 ? { eventType: input.eventType } : {},
2181
+ eventName: asOptionalString(input, "eventName"),
2182
+ path: asOptionalString(input, "path"),
2183
+ selector: asOptionalString(input, "selector"),
2184
+ formId: asOptionalString(input, "formId"),
2185
+ scrollDepth: asOptionalNumber(input, "scrollDepth"),
2186
+ dwellSeconds: asOptionalNumber(input, "dwellSeconds")
2187
+ };
2188
+ return client.analytics.events.update(asString(input, "eventId"), definition);
2189
+ }
2190
+ },
2191
+ {
2192
+ name: "neopress_analytics_event_delete",
2193
+ title: "Delete Analytics Event",
2194
+ description: "Permanently delete a saved analytics event. Events referenced by a funnel cannot be deleted.",
2195
+ inputSchema: {
2196
+ ...siteIdShape,
2197
+ eventId: z.string().uuid()
2198
+ },
2199
+ handler: async (input, context, extra) => {
2200
+ await (await context.createClient({ siteId: siteId(input) }, extra)).analytics.events.delete(asString(input, "eventId"));
2201
+ return { ok: true };
2202
+ }
2203
+ },
2204
+ {
2205
+ name: "neopress_analytics_funnels_list",
2206
+ title: "List Analytics Funnels",
2207
+ description: "List saved analytics funnel definitions for the active site.",
2208
+ inputSchema: siteIdShape,
2209
+ handler: async (input, context, extra) => {
2210
+ return (await context.createClient({ siteId: siteId(input) }, extra)).analytics.funnels.list();
2211
+ }
2212
+ },
2213
+ {
2214
+ name: "neopress_analytics_funnel_get",
2215
+ title: "Get Analytics Funnel",
2216
+ description: "Get a saved analytics funnel definition by UUID.",
2217
+ inputSchema: {
2218
+ ...siteIdShape,
2219
+ funnelId: z.string().uuid()
2220
+ },
2221
+ handler: async (input, context, extra) => {
2222
+ return (await context.createClient({ siteId: siteId(input) }, extra)).analytics.funnels.get(asString(input, "funnelId"));
2223
+ }
2224
+ },
2225
+ {
2226
+ name: "neopress_analytics_funnel_create",
2227
+ title: "Create Analytics Funnel",
2228
+ description: "Create a funnel with 2 to 5 ordered saved event UUIDs. Optional id is a client UUID; reuse it and the same payload after an uncertain response. Step filter is {version:1,root:{kind:'group',op:'and'|'or',children:[groups or {kind:'condition',field,operator,value?,key?}]}}. Fields: event.path/url/referrer/referrer_source/property; session.referrer/referrer_source/traffic_category/utm_source/utm_medium/utm_campaign/utm_content/utm_term. event.property requires key. Operators: eq,neq,contains,not_contains,starts_with,ends_with,exists,not_exists; property also supports gt,gte,lt,lte. Server validates bounds and grouping.",
2229
+ inputSchema: {
2230
+ ...siteIdShape,
2231
+ id: z.string().uuid().optional(),
2232
+ name: z.string(),
2233
+ steps: z.array(z.object({
2234
+ eventId: z.string().uuid(),
2235
+ path: z.string().optional(),
2236
+ filter: z.unknown().optional()
2237
+ })),
2238
+ windowMode: z.enum(["session", "time"]),
2239
+ windowHours: z.number().int().nonnegative().optional()
2240
+ },
2241
+ handler: async (input, context, extra) => {
2242
+ return (await context.createClient({ siteId: siteId(input) }, extra)).analytics.funnels.create({
2243
+ id: asOptionalString(input, "id"),
2244
+ name: asString(input, "name"),
2245
+ steps: input.steps,
2246
+ windowMode: input.windowMode,
2247
+ windowHours: asOptionalNumber(input, "windowHours")
2248
+ });
2249
+ }
2250
+ },
2251
+ {
2252
+ name: "neopress_analytics_funnel_update",
2253
+ title: "Update Analytics Funnel",
2254
+ description: "Replace a saved funnel definition with its ordered event steps and window semantics.",
2255
+ inputSchema: {
2256
+ ...siteIdShape,
2257
+ funnelId: z.string().uuid(),
2258
+ name: z.string(),
2259
+ steps: z.array(z.object({
2260
+ eventId: z.string().uuid(),
2261
+ path: z.string().optional(),
2262
+ filter: z.unknown().optional()
2263
+ })),
2264
+ windowMode: z.enum(["session", "time"]),
2265
+ windowHours: z.number().int().nonnegative().optional()
2266
+ },
2267
+ handler: async (input, context, extra) => {
2268
+ return (await context.createClient({ siteId: siteId(input) }, extra)).analytics.funnels.update(asString(input, "funnelId"), {
2269
+ name: asString(input, "name"),
2270
+ steps: input.steps,
2271
+ windowMode: input.windowMode,
2272
+ windowHours: asOptionalNumber(input, "windowHours")
2273
+ });
2274
+ }
2275
+ },
2276
+ {
2277
+ name: "neopress_analytics_funnel_delete",
2278
+ title: "Delete Analytics Funnel",
2279
+ description: "Permanently delete a saved analytics funnel.",
2280
+ inputSchema: {
2281
+ ...siteIdShape,
2282
+ funnelId: z.string().uuid()
2283
+ },
2284
+ handler: async (input, context, extra) => {
2285
+ await (await context.createClient({ siteId: siteId(input) }, extra)).analytics.funnels.delete(asString(input, "funnelId"));
2286
+ return { ok: true };
2287
+ }
2288
+ },
2289
+ {
2290
+ name: "neopress_analytics_targets_list",
2291
+ title: "List Analytics Event Targets",
2292
+ description: "List site pages and forms available as analytics event targets.",
2293
+ inputSchema: siteIdShape,
2294
+ handler: async (input, context, extra) => {
2295
+ return (await context.createClient({ siteId: siteId(input) }, extra)).analytics.targets();
2296
+ }
2297
+ },
1975
2298
  {
1976
2299
  name: "neopress_analytics_query",
1977
2300
  title: "Query Analytics Pipe",
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@neopress/mcp",
3
- "version": "1.5.0",
3
+ "version": "1.6.0",
4
4
  "description": "Neopress MCP server for first-party AI agents",
5
5
  "type": "module",
6
6
  "bin": {