mcp-server-peecai 0.6.0 → 1.0.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.
Files changed (63) hide show
  1. package/README.md +113 -57
  2. package/dist/api-client.d.ts +15 -4
  3. package/dist/api-client.js +56 -8
  4. package/dist/api-client.js.map +1 -1
  5. package/dist/index.js +71 -15
  6. package/dist/index.js.map +1 -1
  7. package/dist/prompts.js +13 -3
  8. package/dist/prompts.js.map +1 -1
  9. package/dist/schemas.d.ts +239 -0
  10. package/dist/schemas.js +97 -0
  11. package/dist/schemas.js.map +1 -0
  12. package/dist/tools/brands.js +5 -2
  13. package/dist/tools/brands.js.map +1 -1
  14. package/dist/tools/chat-content.js +6 -3
  15. package/dist/tools/chat-content.js.map +1 -1
  16. package/dist/tools/chats.js +5 -2
  17. package/dist/tools/chats.js.map +1 -1
  18. package/dist/tools/models.js +5 -2
  19. package/dist/tools/models.js.map +1 -1
  20. package/dist/tools/projects.js +5 -2
  21. package/dist/tools/projects.js.map +1 -1
  22. package/dist/tools/prompt-suggestions.d.ts +4 -0
  23. package/dist/tools/prompt-suggestions.js +34 -0
  24. package/dist/tools/prompt-suggestions.js.map +1 -0
  25. package/dist/tools/prompts.js +9 -2
  26. package/dist/tools/prompts.js.map +1 -1
  27. package/dist/tools/queries-search.js +3 -2
  28. package/dist/tools/queries-search.js.map +1 -1
  29. package/dist/tools/queries-shopping.js +3 -2
  30. package/dist/tools/queries-shopping.js.map +1 -1
  31. package/dist/tools/report-brands.js +9 -2
  32. package/dist/tools/report-brands.js.map +1 -1
  33. package/dist/tools/report-domains.js +9 -2
  34. package/dist/tools/report-domains.js.map +1 -1
  35. package/dist/tools/report-urls.js +9 -2
  36. package/dist/tools/report-urls.js.map +1 -1
  37. package/dist/tools/suggestion-actions.d.ts +4 -0
  38. package/dist/tools/suggestion-actions.js +80 -0
  39. package/dist/tools/suggestion-actions.js.map +1 -0
  40. package/dist/tools/tags.js +5 -2
  41. package/dist/tools/tags.js.map +1 -1
  42. package/dist/tools/topic-suggestions.d.ts +4 -0
  43. package/dist/tools/topic-suggestions.js +32 -0
  44. package/dist/tools/topic-suggestions.js.map +1 -0
  45. package/dist/tools/topics.js +5 -2
  46. package/dist/tools/topics.js.map +1 -1
  47. package/dist/tools/write-brands.d.ts +4 -0
  48. package/dist/tools/write-brands.js +77 -0
  49. package/dist/tools/write-brands.js.map +1 -0
  50. package/dist/tools/write-prompts.d.ts +4 -0
  51. package/dist/tools/write-prompts.js +76 -0
  52. package/dist/tools/write-prompts.js.map +1 -0
  53. package/dist/tools/write-tags.d.ts +4 -0
  54. package/dist/tools/write-tags.js +77 -0
  55. package/dist/tools/write-tags.js.map +1 -0
  56. package/dist/tools/write-topics.d.ts +4 -0
  57. package/dist/tools/write-topics.js +65 -0
  58. package/dist/tools/write-topics.js.map +1 -0
  59. package/dist/types.d.ts +17 -1
  60. package/dist/util.d.ts +5 -2
  61. package/dist/util.js +15 -1
  62. package/dist/util.js.map +1 -1
  63. package/package.json +2 -1
package/README.md CHANGED
@@ -8,7 +8,7 @@
8
8
  <p align="center">
9
9
  <a href="https://github.com/thein-art/mcp-server-peecai/actions/workflows/ci.yml"><img src="https://img.shields.io/github/actions/workflow/status/thein-art/mcp-server-peecai/ci.yml?branch=main&style=flat-square&label=CI" alt="CI"></a>
10
10
  <img src="https://img.shields.io/badge/node-%3E%3D22-brightgreen?style=flat-square&logo=node.js&logoColor=white" alt="Node.js >= 22">
11
- <img src="https://img.shields.io/badge/MCP-compatible-0098FF?style=flat-square" alt="MCP compatible">
11
+ <img src="https://img.shields.io/badge/MCP-2025--11--25-0098FF?style=flat-square" alt="MCP 2025-11-25">
12
12
  <a href="./LICENSE"><img src="https://img.shields.io/github/license/thein-art/mcp-server-peecai?style=flat-square" alt="License"></a>
13
13
  <a href="https://www.npmjs.com/package/mcp-server-peecai"><img src="https://img.shields.io/npm/v/mcp-server-peecai?style=flat-square" alt="npm"></a>
14
14
  <a href="https://www.npmjs.com/package/mcp-server-peecai"><img src="https://img.shields.io/npm/dm/mcp-server-peecai?style=flat-square" alt="Downloads"></a>
@@ -22,13 +22,15 @@
22
22
 
23
23
  ## What it does
24
24
 
25
- Peec AI tracks how brands appear in AI-generated answers. This MCP server gives any MCP-compatible client direct access to that data — 13 tools covering projects, brands, prompts, chats, query analysis, and analytics reports.
25
+ Peec AI tracks how brands appear in AI-generated answers. This MCP server gives any MCP-compatible client direct access to that data — 31 tools covering projects, brands, prompts, chats, query analysis, analytics reports, and full CRUD operations.
26
26
 
27
27
  **Key capabilities:**
28
28
  - Query brand visibility, sentiment, and position across AI models
29
29
  - Analyze which domains and URLs get cited in AI responses
30
30
  - Inspect individual chat interactions with full source attribution
31
- - Slice data by model, prompt, category tag, or topic
31
+ - Slice data by model, prompt, category tag, topic, country, or date
32
+ - Create, update, and delete brands, prompts, tags, and topics (opt-in)
33
+ - Review and act on AI-generated prompt and topic suggestions
32
34
 
33
35
  ## Quick Start
34
36
 
@@ -104,10 +106,10 @@ Confirm the `peecai` server is connected — in Claude Code run `/mcp`, in VS Co
104
106
 
105
107
  ## Tools
106
108
 
107
- ### Data Retrieval
109
+ ### Data Retrieval (15 tools)
108
110
 
109
111
  **`list_projects`** — List all projects for the company.
110
- - Returns: project IDs, names, statuses (`CUSTOMER` = active, `PITCH_ENDED` = completed)
112
+ - Returns: project IDs, names, statuses (`CUSTOMER` = active, `PITCH` = demo)
111
113
  - Parameters: `limit`, `offset`
112
114
 
113
115
  **`list_brands`** — List tracked brands with their associated domains.
@@ -115,7 +117,7 @@ Confirm the `peecai` server is connected — in Claude Code run `/mcp`, in VS Co
115
117
 
116
118
  **`list_prompts`** — List monitored search prompts.
117
119
  - Returns: prompt messages, tags, topics, user location, search volume
118
- - Parameters: `project_id`, `limit`, `offset`
120
+ - Parameters: `project_id`, `topic_id`, `tag_id`, `limit`, `offset`
119
121
 
120
122
  **`list_tags`** — List category tags for a project.
121
123
  - Parameters: `project_id`, `limit`, `offset`
@@ -127,17 +129,23 @@ Confirm the `peecai` server is connected — in Claude Code run `/mcp`, in VS Co
127
129
  - Returns: model IDs and active status
128
130
  - Parameters: `project_id`, `limit`, `offset`
129
131
 
130
- **`list_chats`** — List AI chat interactions with optional date filtering.
132
+ **`list_chats`** — List AI chat interactions with optional date and dimension filtering.
131
133
  - Returns: chat IDs, prompt/model refs, dates
132
- - Parameters: `project_id`, `start_date`, `end_date`, `limit`, `offset`
134
+ - Parameters: `project_id`, `start_date`, `end_date`, `brand_id`, `prompt_id`, `model_id`, `limit`, `offset`
133
135
 
134
136
  **`get_chat_content`** — Get full content of a specific chat.
135
137
  - Returns: sources (URLs, domains, citation counts), brands mentioned, messages, queries, products
136
138
  - Parameters: `chat_id`, `project_id`
137
139
 
140
+ **`list_prompt_suggestions`** — List AI-generated prompt suggestions.
141
+ - Parameters: `project_id`, `topic_id`, `limit`, `offset`
142
+
143
+ **`list_topic_suggestions`** — List AI-generated topic suggestions.
144
+ - Parameters: `project_id`, `limit`, `offset`
145
+
138
146
  ### Analytics Reports
139
147
 
140
- All report tools support `dimensions` for multi-level breakdowns: `prompt_id`, `model_id`, `tag_id`, `topic_id`. Date filtering via `start_date` / `end_date` (YYYY-MM-DD). All report tools also accept a `filters` parameter for server-side filtering (`field`, `operator: "in" | "not_in"`, `values`). Convenience shortcut `brand_id` is available for the brands report.
148
+ All report tools support `dimensions` for multi-level breakdowns: `prompt_id`, `model_id`, `tag_id`, `topic_id`, `date`, `country_code`. Date filtering via `start_date` / `end_date` (YYYY-MM-DD). Server-side filtering via `filters` parameter (`field`, `operator: "in" | "not_in"`, `values`).
141
149
 
142
150
  **`get_brands_report`** — Brand analytics per brand.
143
151
 
@@ -153,36 +161,57 @@ All report tools support `dimensions` for multi-level breakdowns: `prompt_id`, `
153
161
 
154
162
  | Metric | Description |
155
163
  |--------|-------------|
156
- | `usage_rate` | Share of chats citing this domain (0–1) |
157
- | `citation_avg` | Average citations per chat |
164
+ | `retrieval_rate` | Share of chats retrieving this domain (0–1) |
165
+ | `citation_rate` | Average citations per retrieval |
158
166
  | `classification` | `OWN`, `CORPORATE`, `COMPETITOR`, `EDITORIAL`, `REFERENCE`, `INSTITUTIONAL`, `UGC`, `OTHER` |
159
167
 
160
168
  **`get_urls_report`** — URL-level analytics.
161
169
 
162
170
  | Metric | Description |
163
171
  |--------|-------------|
164
- | `usage_count` | Number of chats citing this URL |
172
+ | `retrievals` | Number of chats retrieving this URL |
165
173
  | `citation_count` | Total citations across all chats |
166
- | `citation_avg` | Average citations per chat |
174
+ | `citation_rate` | Average citations per retrieval |
167
175
  | `classification` | `HOMEPAGE`, `PRODUCT_PAGE`, `CATEGORY_PAGE`, `LISTICLE`, `COMPARISON`, `ARTICLE`, `HOW_TO_GUIDE`, `PROFILE`, `ALTERNATIVE`, `DISCUSSION`, `OTHER` |
168
176
 
169
177
  ### Query Analysis
170
178
 
171
179
  **`search_queries`** — Get search queries AI models generated when answering prompts.
172
- - Returns: actual search queries models used, with prompt/model/chat refs
173
180
  - Parameters: `project_id`, `start_date`, `end_date`, `filters`, `limit`, `offset`
174
181
 
175
182
  **`shopping_queries`** — Get shopping/product queries AI models generated.
176
- - Returns: product-related queries with associated product names
177
183
  - Parameters: `project_id`, `start_date`, `end_date`, `filters`, `limit`, `offset`
178
184
 
179
- ### Tool Annotations
185
+ ### Write Operations (16 tools, opt-in)
186
+
187
+ Write tools are **disabled by default** for safety. Enable them by setting `PEECAI_ALLOW_WRITES=true`.
180
188
 
181
- | Tool | Read-only | Idempotent | Destructive |
182
- |------|:---------:|:----------:|:-----------:|
183
- | All 13 tools | Yes | Yes | No |
189
+ When disabled, these tools are completely invisible they don't appear in `tools/list` and cannot be called by any client.
190
+
191
+ | Entity | Create | Update | Delete |
192
+ |--------|--------|--------|--------|
193
+ | Brands | `create_brand` | `update_brand` | `delete_brand` |
194
+ | Prompts | `create_prompt` | `update_prompt` | `delete_prompt` |
195
+ | Tags | `create_tag` | `update_tag` | `delete_tag` |
196
+ | Topics | `create_topic` | `update_topic` | `delete_topic` |
197
+
198
+ | Suggestions | Accept | Reject |
199
+ |-------------|--------|--------|
200
+ | Prompt suggestions | `accept_prompt_suggestion` | `reject_prompt_suggestion` |
201
+ | Topic suggestions | `accept_topic_suggestion` | `reject_topic_suggestion` |
202
+
203
+ Delete operations are soft-deletes and **irreversible through the API**. Delete tools carry `destructiveHint: true` in their MCP annotations, causing clients like Claude Code to require explicit user approval before execution.
204
+
205
+ ### Tool Annotations
184
206
 
185
- All tools are read-only GET/POST queries against the Peec AI API. No data is modified.
207
+ | Tool type | Read-only | Idempotent | Destructive |
208
+ |-----------|:---------:|:----------:|:-----------:|
209
+ | All read tools (15) | Yes | Yes | No |
210
+ | Create (4) | No | No | No |
211
+ | Update (4) | No | Yes | No |
212
+ | Delete (4) | No | Yes | **Yes** |
213
+ | Accept suggestion (2) | No | No | No |
214
+ | Reject suggestion (2) | No | Yes | No |
186
215
 
187
216
  ## Resources
188
217
 
@@ -197,9 +226,11 @@ MCP resources provide reference data that clients can fetch without a tool call.
197
226
  | `peecai://projects/{project_id}/models` | Template | AI models for a project |
198
227
  | `peecai://projects/{project_id}/prompts` | Template | Prompts for a project |
199
228
 
229
+ Resource templates support listing — clients can enumerate available resources across all projects.
230
+
200
231
  ## Prompt Templates
201
232
 
202
- Guided analytical workflows available as MCP prompts:
233
+ Guided analytical workflows available as MCP prompts. All prompts support `project_id` autocompletion.
203
234
 
204
235
  | Prompt | Description |
205
236
  |--------|-------------|
@@ -215,9 +246,10 @@ Guided analytical workflows available as MCP prompts:
215
246
  "Which domains get cited most in AI search results?"
216
247
  "Compare brand sentiment across ChatGPT and Perplexity"
217
248
  "Show me the full chat content for chat ID abc-123"
218
- "Get URL report broken down by AI model"
249
+ "Get URL report broken down by AI model and country"
219
250
  "What search queries do AI models use when answering my prompts?"
220
- "Show shopping queries generated by AI models last month"
251
+ "Create a brand 'My Brand' with domain mybrand.com"
252
+ "Add a new prompt: 'best CRM software 2025' for country DE"
221
253
  ```
222
254
 
223
255
  ## Environment Variables
@@ -226,6 +258,19 @@ Guided analytical workflows available as MCP prompts:
226
258
  |----------|:--------:|-------------|
227
259
  | `PEECAI_API_KEY` | Yes | API key from [app.peec.ai](https://app.peec.ai/api-keys) |
228
260
  | `PEECAI_PROJECT_ID` | No | Default project ID — saves repeating it in every tool call |
261
+ | `PEECAI_ALLOW_WRITES` | No | Set to `true` to enable write operations (create/update/delete). Disabled by default for safety. |
262
+
263
+ ## MCP Protocol Features
264
+
265
+ This server implements the MCP 2025-11-25 specification:
266
+
267
+ - **Structured content** — list tools return `structuredContent` alongside text for type-safe client parsing
268
+ - **Tool annotations** — `readOnlyHint`, `destructiveHint`, `idempotentHint` on every tool
269
+ - **Progress notifications** — report tools send progress updates when the client provides a `progressToken`
270
+ - **Structured logging** — API errors are sent as MCP log notifications with endpoint, status, and message context
271
+ - **Prompt completions** — `project_id` argument supports autocompletion via `completable()`
272
+ - **Resource templates** — with `list` callbacks for enumerating resources across projects
273
+ - **Cancellation support** — all tools forward the MCP `AbortSignal` to API calls
229
274
 
230
275
  ## API Drift Detection
231
276
 
@@ -238,12 +283,6 @@ npm run check:api-drift
238
283
  - **No drift**: exit code 0, snapshot is current
239
284
  - **Drift detected**: exit code 1, shows a diff of changes
240
285
 
241
- When drift is detected:
242
- 1. Review the diff to understand what changed
243
- 2. Update the snapshot: `curl -s https://api.peec.ai/customer/v1/openapi/json -o api-spec/openapi-snapshot.json`
244
- 3. Update `src/types.ts` and tools as needed
245
- 4. Run tests to verify
246
-
247
286
  No API key is required — the OpenAPI spec is publicly accessible.
248
287
 
249
288
  ## Development
@@ -256,41 +295,58 @@ No API key is required — the OpenAPI spec is publicly accessible.
256
295
  ### Commands
257
296
 
258
297
  ```bash
259
- npm install # Install dependencies
260
- npm run build # Compile TypeScript to dist/
261
- npm run dev # Watch mode — recompile on changes
262
- npm test # Run tests
263
- npm run test:watch # Run tests in watch mode
298
+ npm install # Install dependencies
299
+ npm run build # Compile TypeScript to dist/
300
+ npm run dev # Watch mode — recompile on changes
301
+ npm test # Run unit tests (358 tests)
302
+ npm run test:watch # Run tests in watch mode
303
+ npm run test:integration # Run integration tests (requires PEECAI_API_KEY)
264
304
  npm run check:api-drift # Check for API spec changes
265
305
  ```
266
306
 
307
+ ### Integration Tests
308
+
309
+ Integration tests hit the live Peec AI API and are skipped by default in `npm test`.
310
+
311
+ ```bash
312
+ # Read-only smoke test (all 15 read tools + prompts + resources)
313
+ PEECAI_API_KEY=xxx npm run test:integration
314
+
315
+ # Full CRUD round-trip (requires a test project + write access)
316
+ PEECAI_ALLOW_WRITES=true PEECAI_TEST_PROJECT_ID=or_xxx npm run test:integration
317
+ ```
318
+
267
319
  ### Project Structure
268
320
 
269
321
  ```
270
322
  src/
271
- ├── index.ts # Server entry point, tool registration
272
- ├── api-client.ts # HTTP client for Peec AI Customer API
273
- ├── types.ts # TypeScript interfaces for API responses
274
- ├── util.ts # Shared validation, date handling, MCP response helpers
275
- ├── prompts.ts # MCP prompt templates (guided workflows)
276
- └── tools/ # One file per MCP tool
277
- ├── projects.ts
278
- ├── brands.ts
279
- ├── prompts.ts
280
- ├── tags.ts
281
- ├── topics.ts
282
- ├── models.ts
283
- ├── chats.ts
284
- ├── chat-content.ts
285
- ├── report-brands.ts
286
- ├── report-domains.ts
287
- ├── report-urls.ts
288
- ├── queries-search.ts
289
- └── queries-shopping.ts
290
- scripts/ # Development and CI scripts
291
- └── check-api-drift.sh
292
- api-spec/ # API specification snapshots
293
- └── openapi-snapshot.json
323
+ ├── index.ts # Server entry point, tool/resource/prompt registration
324
+ ├── api-client.ts # HTTP client for Peec AI Customer API
325
+ ├── types.ts # TypeScript interfaces for API responses
326
+ ├── schemas.ts # Zod output schemas for structured content
327
+ ├── util.ts # Validation, date handling, MCP response helpers
328
+ ├── prompts.ts # MCP prompt templates (guided workflows)
329
+ └── tools/ # One file per MCP tool (or tool group)
330
+ ├── projects.ts # list_projects
331
+ ├── brands.ts # list_brands
332
+ ├── prompts.ts # list_prompts
333
+ ├── tags.ts # list_tags
334
+ ├── topics.ts # list_topics
335
+ ├── models.ts # list_models
336
+ ├── chats.ts # list_chats
337
+ ├── chat-content.ts # get_chat_content
338
+ ├── prompt-suggestions.ts # list_prompt_suggestions
339
+ ├── topic-suggestions.ts # list_topic_suggestions
340
+ ├── report-brands.ts # get_brands_report
341
+ ├── report-domains.ts # get_domains_report
342
+ ├── report-urls.ts # get_urls_report
343
+ ├── queries-search.ts # search_queries
344
+ ├── queries-shopping.ts # shopping_queries
345
+ ├── write-brands.ts # create/update/delete brand
346
+ ├── write-prompts.ts # create/update/delete prompt
347
+ ├── write-tags.ts # create/update/delete tag
348
+ ├── write-topics.ts # create/update/delete topic
349
+ └── suggestion-actions.ts # accept/reject suggestions
294
350
  ```
295
351
 
296
352
  ## License
@@ -1,16 +1,27 @@
1
+ /** Callback for structured logging of API events. */
2
+ export type ApiLogCallback = (level: "error" | "warning" | "info", data: Record<string, unknown>) => void;
1
3
  /**
2
4
  * HTTP client for the Peec AI Customer API.
3
5
  * Handles authentication, query parameters, timeouts, and error formatting.
4
6
  */
5
7
  export declare class PeecApiClient {
6
8
  private readonly apiKey;
7
- constructor(apiKey: string);
9
+ private readonly onLog?;
10
+ constructor(apiKey: string, onLog?: ApiLogCallback);
8
11
  /** GET request that unwraps the `{ data: T }` envelope. Use for list/paginated endpoints. */
9
- get<T>(path: string, params?: Record<string, string | number | undefined>): Promise<T>;
12
+ get<T>(path: string, params?: Record<string, string | number | undefined>, signal?: AbortSignal): Promise<T>;
10
13
  /** GET request that returns the response body directly. Use for endpoints without a `data` envelope (e.g. chat content). */
11
- getRaw<T>(path: string, params?: Record<string, string | number | undefined>): Promise<T>;
14
+ getRaw<T>(path: string, params?: Record<string, string | number | undefined>, signal?: AbortSignal): Promise<T>;
12
15
  /** POST request that unwraps the `{ data: T }` envelope. Use for analytics report endpoints. */
13
- post<T>(path: string, body: Record<string, unknown>, params?: Record<string, string | undefined>): Promise<T>;
16
+ post<T>(path: string, body: Record<string, unknown>, params?: Record<string, string | undefined>, signal?: AbortSignal): Promise<T>;
17
+ /** POST request that returns the response body directly. Use for create endpoints without `data` envelope. */
18
+ postRaw<T>(path: string, body: Record<string, unknown>, params?: Record<string, string | undefined>, signal?: AbortSignal): Promise<T>;
19
+ /** PATCH request that unwraps the `{ data: T }` envelope. Use for update endpoints. */
20
+ patch<T>(path: string, body: Record<string, unknown>, params?: Record<string, string | undefined>, signal?: AbortSignal): Promise<T>;
21
+ /** PATCH request that returns the response body directly. Use for update endpoints without `data` envelope. */
22
+ patchRaw<T>(path: string, body: Record<string, unknown>, params?: Record<string, string | undefined>, signal?: AbortSignal): Promise<T>;
23
+ /** DELETE request. Returns void — the API returns an empty body on success. */
24
+ delete(path: string, params?: Record<string, string | undefined>, signal?: AbortSignal): Promise<void>;
14
25
  private request;
15
26
  /**
16
27
  * Builds a human-readable error message from a failed API response.
@@ -7,31 +7,72 @@ const MAX_ERROR_LENGTH = 500;
7
7
  */
8
8
  export class PeecApiClient {
9
9
  apiKey;
10
- constructor(apiKey) {
10
+ onLog;
11
+ constructor(apiKey, onLog) {
11
12
  this.apiKey = apiKey;
13
+ this.onLog = onLog;
12
14
  }
13
15
  /** GET request that unwraps the `{ data: T }` envelope. Use for list/paginated endpoints. */
14
- async get(path, params) {
15
- const response = await this.request(path, { method: "GET", params });
16
+ async get(path, params, signal) {
17
+ const response = await this.request(path, { method: "GET", params, signal });
16
18
  const json = await response.json();
17
19
  return json.data;
18
20
  }
19
21
  /** GET request that returns the response body directly. Use for endpoints without a `data` envelope (e.g. chat content). */
20
- async getRaw(path, params) {
21
- const response = await this.request(path, { method: "GET", params });
22
+ async getRaw(path, params, signal) {
23
+ const response = await this.request(path, { method: "GET", params, signal });
22
24
  return response.json();
23
25
  }
24
26
  /** POST request that unwraps the `{ data: T }` envelope. Use for analytics report endpoints. */
25
- async post(path, body, params) {
27
+ async post(path, body, params, signal) {
26
28
  const response = await this.request(path, {
27
29
  method: "POST",
28
30
  params,
29
31
  body: JSON.stringify(body),
30
32
  extraHeaders: { "Content-Type": "application/json" },
33
+ signal,
31
34
  });
32
35
  const json = await response.json();
33
36
  return json.data;
34
37
  }
38
+ /** POST request that returns the response body directly. Use for create endpoints without `data` envelope. */
39
+ async postRaw(path, body, params, signal) {
40
+ const response = await this.request(path, {
41
+ method: "POST",
42
+ params,
43
+ body: JSON.stringify(body),
44
+ extraHeaders: { "Content-Type": "application/json" },
45
+ signal,
46
+ });
47
+ return response.json();
48
+ }
49
+ /** PATCH request that unwraps the `{ data: T }` envelope. Use for update endpoints. */
50
+ async patch(path, body, params, signal) {
51
+ const response = await this.request(path, {
52
+ method: "PATCH",
53
+ params,
54
+ body: JSON.stringify(body),
55
+ extraHeaders: { "Content-Type": "application/json" },
56
+ signal,
57
+ });
58
+ const json = await response.json();
59
+ return json.data;
60
+ }
61
+ /** PATCH request that returns the response body directly. Use for update endpoints without `data` envelope. */
62
+ async patchRaw(path, body, params, signal) {
63
+ const response = await this.request(path, {
64
+ method: "PATCH",
65
+ params,
66
+ body: JSON.stringify(body),
67
+ extraHeaders: { "Content-Type": "application/json" },
68
+ signal,
69
+ });
70
+ return response.json();
71
+ }
72
+ /** DELETE request. Returns void — the API returns an empty body on success. */
73
+ async delete(path, params, signal) {
74
+ await this.request(path, { method: "DELETE", params, signal });
75
+ }
35
76
  async request(path, options) {
36
77
  const url = new URL(`${BASE_URL}${path}`);
37
78
  if (options.params) {
@@ -41,6 +82,11 @@ export class PeecApiClient {
41
82
  }
42
83
  }
43
84
  }
85
+ // Combine caller signal (MCP cancellation) with timeout signal
86
+ const timeoutSignal = AbortSignal.timeout(REQUEST_TIMEOUT_MS);
87
+ const signal = options.signal
88
+ ? AbortSignal.any([options.signal, timeoutSignal])
89
+ : timeoutSignal;
44
90
  const response = await fetch(url.toString(), {
45
91
  method: options.method,
46
92
  headers: {
@@ -49,10 +95,12 @@ export class PeecApiClient {
49
95
  ...options.extraHeaders,
50
96
  },
51
97
  body: options.body,
52
- signal: AbortSignal.timeout(REQUEST_TIMEOUT_MS),
98
+ signal,
53
99
  });
54
100
  if (!response.ok) {
55
- throw new Error(await this.formatError(response));
101
+ const errorMessage = await this.formatError(response);
102
+ this.onLog?.("error", { endpoint: path, method: options.method, status: response.status, message: errorMessage });
103
+ throw new Error(errorMessage);
56
104
  }
57
105
  return response;
58
106
  }
@@ -1 +1 @@
1
- {"version":3,"file":"api-client.js","sourceRoot":"","sources":["../src/api-client.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"api-client.js","sourceRoot":"","sources":["../src/api-client.ts"],"names":[],"mappings":"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"}
package/dist/index.js CHANGED
@@ -22,6 +22,13 @@ import { registerDomainsReportTool } from "./tools/report-domains.js";
22
22
  import { registerUrlsReportTool } from "./tools/report-urls.js";
23
23
  import { registerSearchQueriesTool } from "./tools/queries-search.js";
24
24
  import { registerShoppingQueriesTool } from "./tools/queries-shopping.js";
25
+ import { registerPromptSuggestionsTool } from "./tools/prompt-suggestions.js";
26
+ import { registerTopicSuggestionsTool } from "./tools/topic-suggestions.js";
27
+ import { registerWriteBrandsTools } from "./tools/write-brands.js";
28
+ import { registerWritePromptsTools } from "./tools/write-prompts.js";
29
+ import { registerWriteTagsTools } from "./tools/write-tags.js";
30
+ import { registerWriteTopicsTools } from "./tools/write-topics.js";
31
+ import { registerSuggestionActionTools } from "./tools/suggestion-actions.js";
25
32
  import { registerPromptTemplates } from "./prompts.js";
26
33
  import { createRequire } from "node:module";
27
34
  const require = createRequire(import.meta.url);
@@ -31,14 +38,36 @@ if (!apiKey) {
31
38
  console.error("PEECAI_API_KEY environment variable is required");
32
39
  process.exit(1);
33
40
  }
34
- const client = new PeecApiClient(apiKey);
41
+ const allowWrites = process.env.PEECAI_ALLOW_WRITES === "true";
35
42
  const server = new McpServer({ name: "peecai", version }, {
36
- instructions: "This server provides AI search analytics from Peec AI. " +
37
- "Most tools require a project_id parameter — call list_projects first to find available project IDs. " +
38
- "If PEECAI_PROJECT_ID is set, it will be used as the default when project_id is omitted. " +
39
- "For reports (brands, domains, URLs), specify date ranges with start_date/end_date. " +
40
- "Use search_queries and shopping_queries to see what queries AI models generated. " +
41
- "Use list_brands, list_models, list_prompts to resolve IDs returned in reports.",
43
+ capabilities: { logging: {} },
44
+ instructions: [
45
+ "This server provides AI search analytics from Peec AI.",
46
+ "",
47
+ "## Getting started",
48
+ "Most tools require a project_id — call list_projects first to find available project IDs.",
49
+ "If PEECAI_PROJECT_ID is set, it will be used as the default when project_id is omitted.",
50
+ "",
51
+ "## Analytics workflow",
52
+ "1. list_projects → pick a project ID",
53
+ "2. list_brands / list_prompts / list_models → understand dimensions",
54
+ "3. get_brands_report / get_domains_report / get_urls_report → analytics with date ranges and dimensional breakdowns",
55
+ "4. search_queries / shopping_queries → see what queries AI models generated",
56
+ "5. list_chats → find specific chats, then get_chat_content for full details",
57
+ "",
58
+ "## Reports",
59
+ "Specify date ranges with start_date/end_date (YYYY-MM-DD). Use dimensions to break down by model, prompt, tag, topic, date, or country.",
60
+ "Use filters for server-side filtering. Default limit is 100; max is 10000.",
61
+ "",
62
+ "## Suggestions",
63
+ "list_prompt_suggestions / list_topic_suggestions show AI-generated suggestions that can be reviewed.",
64
+ allowWrites
65
+ ? "\n## Write operations (enabled)\nCRUD tools are available for brands, prompts, tags, and topics. Suggestion accept/reject tools are also available. Delete operations are soft-deletes and irreversible through the API."
66
+ : "",
67
+ ].join("\n"),
68
+ });
69
+ const client = new PeecApiClient(apiKey, (level, data) => {
70
+ server.sendLoggingMessage({ level, logger: "peecai-api", data }).catch(() => { });
42
71
  });
43
72
  // Register tools
44
73
  registerProjectsTool(server, client);
@@ -54,10 +83,21 @@ registerDomainsReportTool(server, client);
54
83
  registerUrlsReportTool(server, client);
55
84
  registerSearchQueriesTool(server, client);
56
85
  registerShoppingQueriesTool(server, client);
86
+ registerPromptSuggestionsTool(server, client);
87
+ registerTopicSuggestionsTool(server, client);
88
+ // Register write tools (gated by PEECAI_ALLOW_WRITES)
89
+ if (allowWrites) {
90
+ registerWriteBrandsTools(server, client);
91
+ registerWritePromptsTools(server, client);
92
+ registerWriteTagsTools(server, client);
93
+ registerWriteTopicsTools(server, client);
94
+ registerSuggestionActionTools(server, client);
95
+ }
57
96
  // Register MCP prompts (guided workflows)
58
97
  registerPromptTemplates(server, client);
59
98
  // Register resources
60
99
  server.registerResource("projects", "peecai://projects", {
100
+ title: "Peec AI Projects",
61
101
  description: "List all available Peec AI projects for the authenticated account.",
62
102
  mimeType: "application/json",
63
103
  }, async () => {
@@ -78,14 +118,30 @@ server.registerResource("projects", "peecai://projects", {
78
118
  });
79
119
  // Register resource templates for dimension lookups
80
120
  const dimensionResources = [
81
- { name: "brands", endpoint: "/brands", description: "Tracked brands and their domains for a project." },
82
- { name: "tags", endpoint: "/tags", description: "Category tags for a project." },
83
- { name: "topics", endpoint: "/topics", description: "Topic groupings for a project." },
84
- { name: "models", endpoint: "/models", description: "AI models tracked by Peec AI for a project." },
85
- { name: "prompts", endpoint: "/prompts", description: "Search prompts monitored across AI models for a project." },
121
+ { name: "brands", title: "Brands", endpoint: "/brands", description: "Tracked brands and their domains for a project." },
122
+ { name: "tags", title: "Tags", endpoint: "/tags", description: "Category tags for a project." },
123
+ { name: "topics", title: "Topics", endpoint: "/topics", description: "Topic groupings for a project." },
124
+ { name: "models", title: "AI Models", endpoint: "/models", description: "AI models tracked by Peec AI for a project." },
125
+ { name: "prompts", title: "Prompts", endpoint: "/prompts", description: "Search prompts monitored across AI models for a project." },
86
126
  ];
87
- for (const { name, endpoint, description } of dimensionResources) {
88
- server.registerResource(name, new ResourceTemplate(`peecai://projects/{project_id}/${name}`, { list: undefined }), { description, mimeType: "application/json" }, async (uri, { project_id }) => {
127
+ for (const { name, title, endpoint, description } of dimensionResources) {
128
+ server.registerResource(name, new ResourceTemplate(`peecai://projects/{project_id}/${name}`, {
129
+ list: async () => {
130
+ try {
131
+ const projects = await client.get("/projects", { limit: 1000 });
132
+ return {
133
+ resources: projects.map((p) => ({
134
+ uri: `peecai://projects/${p.id}/${name}`,
135
+ name: `${p.name} — ${title}`,
136
+ mimeType: "application/json",
137
+ })),
138
+ };
139
+ }
140
+ catch {
141
+ return { resources: [] };
142
+ }
143
+ },
144
+ }), { title, description, mimeType: "application/json" }, async (uri, { project_id }) => {
89
145
  try {
90
146
  const data = await client.get(endpoint, {
91
147
  project_id: String(project_id),
@@ -108,7 +164,7 @@ for (const { name, endpoint, description } of dimensionResources) {
108
164
  async function main() {
109
165
  const transport = new StdioServerTransport();
110
166
  await server.connect(transport);
111
- console.error("Peec AI MCP server running on stdio");
167
+ console.error(`Peec AI MCP server running on stdio${allowWrites ? " (write tools enabled)" : ""}`);
112
168
  // Graceful shutdown with timeout fallback
113
169
  const shutdown = async () => {
114
170
  console.error("Shutting down Peec AI MCP server…");
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}