mcp-server-peecai 0.2.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/LICENSE +21 -0
- package/README.md +271 -0
- package/dist/api-client.d.ts +21 -0
- package/dist/api-client.js +83 -0
- package/dist/api-client.js.map +1 -0
- package/dist/index.d.ts +9 -0
- package/dist/index.js +79 -0
- package/dist/index.js.map +1 -0
- package/dist/prompts.d.ts +3 -0
- package/dist/prompts.js +100 -0
- package/dist/prompts.js.map +1 -0
- package/dist/tools/brands.d.ts +4 -0
- package/dist/tools/brands.js +25 -0
- package/dist/tools/brands.js.map +1 -0
- package/dist/tools/chat-content.d.ts +4 -0
- package/dist/tools/chat-content.js +23 -0
- package/dist/tools/chat-content.js.map +1 -0
- package/dist/tools/chats.d.ts +4 -0
- package/dist/tools/chats.js +30 -0
- package/dist/tools/chats.js.map +1 -0
- package/dist/tools/models.d.ts +4 -0
- package/dist/tools/models.js +25 -0
- package/dist/tools/models.js.map +1 -0
- package/dist/tools/projects.d.ts +4 -0
- package/dist/tools/projects.js +20 -0
- package/dist/tools/projects.js.map +1 -0
- package/dist/tools/prompts.d.ts +4 -0
- package/dist/tools/prompts.js +25 -0
- package/dist/tools/prompts.js.map +1 -0
- package/dist/tools/report-brands.d.ts +4 -0
- package/dist/tools/report-brands.js +47 -0
- package/dist/tools/report-brands.js.map +1 -0
- package/dist/tools/report-domains.d.ts +4 -0
- package/dist/tools/report-domains.js +47 -0
- package/dist/tools/report-domains.js.map +1 -0
- package/dist/tools/report-urls.d.ts +4 -0
- package/dist/tools/report-urls.js +47 -0
- package/dist/tools/report-urls.js.map +1 -0
- package/dist/tools/tags.d.ts +4 -0
- package/dist/tools/tags.js +25 -0
- package/dist/tools/tags.js.map +1 -0
- package/dist/tools/topics.d.ts +4 -0
- package/dist/tools/topics.js +25 -0
- package/dist/tools/topics.js.map +1 -0
- package/dist/types.d.ts +149 -0
- package/dist/types.js +2 -0
- package/dist/types.js.map +1 -0
- package/dist/util.d.ts +89 -0
- package/dist/util.js +152 -0
- package/dist/util.js.map +1 -0
- package/package.json +56 -0
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 Tobias Hein
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
package/README.md
ADDED
|
@@ -0,0 +1,271 @@
|
|
|
1
|
+
<p align="center">
|
|
2
|
+
<h1 align="center">Peec.ai MCP Server</h1>
|
|
3
|
+
<p align="center">
|
|
4
|
+
Community-built MCP server for the <a href="https://peec.ai">Peec.ai</a> API — AI Search Analytics for brand visibility, sentiment, and citations across ChatGPT, Perplexity, and other AI models.
|
|
5
|
+
</p>
|
|
6
|
+
</p>
|
|
7
|
+
|
|
8
|
+
<p align="center">
|
|
9
|
+
<img src="https://img.shields.io/badge/node-%3E%3D22-brightgreen?style=flat-square&logo=node.js&logoColor=white" alt="Node.js >= 22">
|
|
10
|
+
<img src="https://img.shields.io/badge/MCP-compatible-0098FF?style=flat-square" alt="MCP compatible">
|
|
11
|
+
</p>
|
|
12
|
+
|
|
13
|
+
> **Note:** This is an unofficial community project, not affiliated with or endorsed by Peec.ai. It requires a [Peec.ai](https://peec.ai) account and API key.
|
|
14
|
+
|
|
15
|
+
> **API Beta:** The Peec.ai API is currently in beta — endpoints, payloads, and responses may change. Access is limited to Enterprise customers.
|
|
16
|
+
|
|
17
|
+
---
|
|
18
|
+
|
|
19
|
+
## What it does
|
|
20
|
+
|
|
21
|
+
Peec.ai tracks how brands appear in AI-generated answers. This MCP server gives Claude direct access to that data — 11 tools covering projects, brands, prompts, chats, and analytics reports.
|
|
22
|
+
|
|
23
|
+
**Key capabilities:**
|
|
24
|
+
- Query brand visibility, sentiment, and position across AI models
|
|
25
|
+
- Analyze which domains and URLs get cited in AI responses
|
|
26
|
+
- Inspect individual chat interactions with full source attribution
|
|
27
|
+
- Slice data by model, prompt, category tag, or topic
|
|
28
|
+
|
|
29
|
+
## Quick Start
|
|
30
|
+
|
|
31
|
+
### 1. Get your API key
|
|
32
|
+
|
|
33
|
+
Sign up at [app.peec.ai](https://app.peec.ai) and create an API key under **Settings > API Keys**.
|
|
34
|
+
|
|
35
|
+
### 2. Install
|
|
36
|
+
|
|
37
|
+
```bash
|
|
38
|
+
git clone https://github.com/thein-art/mcp-server-peecai.git
|
|
39
|
+
cd mcp-server-peecai
|
|
40
|
+
npm install && npm run build
|
|
41
|
+
```
|
|
42
|
+
|
|
43
|
+
### 3. Configure
|
|
44
|
+
|
|
45
|
+
<details open>
|
|
46
|
+
<summary><strong>Claude Code</strong></summary>
|
|
47
|
+
|
|
48
|
+
The repository includes a `.mcp.json` for automatic setup. Set the environment variables and Claude Code will pick it up:
|
|
49
|
+
|
|
50
|
+
```bash
|
|
51
|
+
export PEECAI_API_KEY="your-api-key"
|
|
52
|
+
export PEECAI_PROJECT_ID="your-project-id" # optional default
|
|
53
|
+
```
|
|
54
|
+
|
|
55
|
+
Or add manually:
|
|
56
|
+
|
|
57
|
+
```bash
|
|
58
|
+
claude mcp add --transport stdio peecai -- node /path/to/mcp-server-peecai/dist/index.js
|
|
59
|
+
```
|
|
60
|
+
|
|
61
|
+
</details>
|
|
62
|
+
|
|
63
|
+
<details>
|
|
64
|
+
<summary><strong>Claude Desktop</strong></summary>
|
|
65
|
+
|
|
66
|
+
Add to your `claude_desktop_config.json`:
|
|
67
|
+
|
|
68
|
+
```json
|
|
69
|
+
{
|
|
70
|
+
"mcpServers": {
|
|
71
|
+
"peecai": {
|
|
72
|
+
"command": "node",
|
|
73
|
+
"args": ["/path/to/mcp-server-peecai/dist/index.js"],
|
|
74
|
+
"env": {
|
|
75
|
+
"PEECAI_API_KEY": "your-api-key",
|
|
76
|
+
"PEECAI_PROJECT_ID": "your-project-id"
|
|
77
|
+
}
|
|
78
|
+
}
|
|
79
|
+
}
|
|
80
|
+
}
|
|
81
|
+
```
|
|
82
|
+
|
|
83
|
+
</details>
|
|
84
|
+
|
|
85
|
+
<details>
|
|
86
|
+
<summary><strong>VS Code / Cursor</strong></summary>
|
|
87
|
+
|
|
88
|
+
Add to `.vscode/mcp.json` in your workspace:
|
|
89
|
+
|
|
90
|
+
```json
|
|
91
|
+
{
|
|
92
|
+
"servers": {
|
|
93
|
+
"peecai": {
|
|
94
|
+
"command": "node",
|
|
95
|
+
"args": ["/path/to/mcp-server-peecai/dist/index.js"],
|
|
96
|
+
"env": {
|
|
97
|
+
"PEECAI_API_KEY": "your-api-key",
|
|
98
|
+
"PEECAI_PROJECT_ID": "your-project-id"
|
|
99
|
+
}
|
|
100
|
+
}
|
|
101
|
+
}
|
|
102
|
+
}
|
|
103
|
+
```
|
|
104
|
+
|
|
105
|
+
</details>
|
|
106
|
+
|
|
107
|
+
### 4. Verify
|
|
108
|
+
|
|
109
|
+
In Claude Code, run `/mcp` to confirm the `peecai` server is connected.
|
|
110
|
+
|
|
111
|
+
## Tools
|
|
112
|
+
|
|
113
|
+
### Data Retrieval
|
|
114
|
+
|
|
115
|
+
**`list_projects`** — List all projects for the company.
|
|
116
|
+
- Returns: project IDs, names, statuses (`CUSTOMER` = active, `PITCH_ENDED` = completed)
|
|
117
|
+
- Parameters: `limit`, `offset`
|
|
118
|
+
|
|
119
|
+
**`list_brands`** — List tracked brands with their associated domains.
|
|
120
|
+
- Parameters: `project_id`, `limit`, `offset`
|
|
121
|
+
|
|
122
|
+
**`list_prompts`** — List monitored search prompts.
|
|
123
|
+
- Returns: prompt messages, tags, topics, user location, search volume
|
|
124
|
+
- Parameters: `project_id`, `limit`, `offset`
|
|
125
|
+
|
|
126
|
+
**`list_tags`** — List category tags for a project.
|
|
127
|
+
- Parameters: `project_id`, `limit`, `offset`
|
|
128
|
+
|
|
129
|
+
**`list_topics`** — List topic groupings for a project.
|
|
130
|
+
- Parameters: `project_id`, `limit`, `offset`
|
|
131
|
+
|
|
132
|
+
**`list_models`** — List tracked AI models (ChatGPT, Perplexity, etc.).
|
|
133
|
+
- Returns: model IDs and active status
|
|
134
|
+
- Parameters: `project_id`, `limit`, `offset`
|
|
135
|
+
|
|
136
|
+
**`list_chats`** — List AI chat interactions with optional date filtering.
|
|
137
|
+
- Returns: chat IDs, prompt/model refs, dates
|
|
138
|
+
- Parameters: `project_id`, `start_date`, `end_date`, `limit`, `offset`
|
|
139
|
+
|
|
140
|
+
**`get_chat_content`** — Get full content of a specific chat.
|
|
141
|
+
- Returns: sources (URLs, domains, citation counts), brands mentioned, messages, queries, products
|
|
142
|
+
- Parameters: `chat_id`, `project_id`
|
|
143
|
+
|
|
144
|
+
### Analytics Reports
|
|
145
|
+
|
|
146
|
+
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 shortcuts `brand_id` / `classification` remain available.
|
|
147
|
+
|
|
148
|
+
**`get_brands_report`** — Brand analytics per brand.
|
|
149
|
+
|
|
150
|
+
| Metric | Description |
|
|
151
|
+
|--------|-------------|
|
|
152
|
+
| `visibility` | Ratio 0–1 (visibility_count / visibility_total) |
|
|
153
|
+
| `sentiment` | Score 0–100, 50 = neutral |
|
|
154
|
+
| `position` | Average rank when mentioned, lower = better |
|
|
155
|
+
| `share_of_voice` | Share of voice 0–1 (proportion of total mentions) |
|
|
156
|
+
| `mention_count` | Number of times the brand was mentioned |
|
|
157
|
+
|
|
158
|
+
**`get_domains_report`** — Domain-level analytics.
|
|
159
|
+
|
|
160
|
+
| Metric | Description |
|
|
161
|
+
|--------|-------------|
|
|
162
|
+
| `usage_rate` | Share of chats citing this domain (0–1) |
|
|
163
|
+
| `citation_avg` | Average citations per chat |
|
|
164
|
+
| `classification` | `OWN`, `CORPORATE`, `COMPETITOR`, `EDITORIAL`, `REFERENCE`, `INSTITUTIONAL`, `UGC`, `OTHER` |
|
|
165
|
+
|
|
166
|
+
**`get_urls_report`** — URL-level analytics.
|
|
167
|
+
|
|
168
|
+
| Metric | Description |
|
|
169
|
+
|--------|-------------|
|
|
170
|
+
| `usage_count` | Number of chats citing this URL |
|
|
171
|
+
| `citation_count` | Total citations across all chats |
|
|
172
|
+
| `citation_avg` | Average citations per chat |
|
|
173
|
+
| `classification` | `HOMEPAGE`, `PRODUCT_PAGE`, `CATEGORY_PAGE`, `LISTICLE`, `COMPARISON`, `ARTICLE`, `HOW_TO_GUIDE`, `PROFILE`, `ALTERNATIVE`, `DISCUSSION`, `OTHER` |
|
|
174
|
+
|
|
175
|
+
### Tool Annotations
|
|
176
|
+
|
|
177
|
+
| Tool | Read-only | Idempotent | Destructive |
|
|
178
|
+
|------|:---------:|:----------:|:-----------:|
|
|
179
|
+
| All 11 tools | Yes | Yes | No |
|
|
180
|
+
|
|
181
|
+
All tools are read-only GET/POST queries against the Peec.ai API. No data is modified.
|
|
182
|
+
|
|
183
|
+
## Example Prompts
|
|
184
|
+
|
|
185
|
+
```
|
|
186
|
+
"List my Peec.ai projects"
|
|
187
|
+
"Show brand visibility for the last 30 days"
|
|
188
|
+
"Which domains get cited most in AI search results?"
|
|
189
|
+
"Compare brand sentiment across ChatGPT and Perplexity"
|
|
190
|
+
"Show me the full chat content for chat ID abc-123"
|
|
191
|
+
"Get URL report broken down by AI model"
|
|
192
|
+
```
|
|
193
|
+
|
|
194
|
+
## Environment Variables
|
|
195
|
+
|
|
196
|
+
| Variable | Required | Description |
|
|
197
|
+
|----------|:--------:|-------------|
|
|
198
|
+
| `PEECAI_API_KEY` | Yes | API key from [app.peec.ai](https://app.peec.ai/api-keys) |
|
|
199
|
+
| `PEECAI_PROJECT_ID` | No | Default project ID — saves repeating it in every tool call |
|
|
200
|
+
|
|
201
|
+
## API Drift Detection
|
|
202
|
+
|
|
203
|
+
The Peec.ai API is in beta and may change. A drift detection script compares the live OpenAPI spec against a committed snapshot:
|
|
204
|
+
|
|
205
|
+
```bash
|
|
206
|
+
npm run check:api-drift
|
|
207
|
+
```
|
|
208
|
+
|
|
209
|
+
- **No drift**: exit code 0, snapshot is current
|
|
210
|
+
- **Drift detected**: exit code 1, shows a diff of changes
|
|
211
|
+
|
|
212
|
+
When drift is detected:
|
|
213
|
+
1. Review the diff to understand what changed
|
|
214
|
+
2. Update the snapshot: `curl -s https://api.peec.ai/customer/v1/openapi/json -o api-spec/openapi-snapshot.json`
|
|
215
|
+
3. Update `src/types.ts` and tools as needed
|
|
216
|
+
4. Run tests to verify
|
|
217
|
+
|
|
218
|
+
No API key is required — the OpenAPI spec is publicly accessible.
|
|
219
|
+
|
|
220
|
+
## Development
|
|
221
|
+
|
|
222
|
+
### Prerequisites
|
|
223
|
+
|
|
224
|
+
- Node.js >= 22
|
|
225
|
+
- npm
|
|
226
|
+
|
|
227
|
+
### Commands
|
|
228
|
+
|
|
229
|
+
```bash
|
|
230
|
+
npm install # Install dependencies
|
|
231
|
+
npm run build # Compile TypeScript to dist/
|
|
232
|
+
npm run dev # Watch mode — recompile on changes
|
|
233
|
+
npm test # Run tests
|
|
234
|
+
npm run test:watch # Run tests in watch mode
|
|
235
|
+
npm run check:api-drift # Check for API spec changes
|
|
236
|
+
```
|
|
237
|
+
|
|
238
|
+
### Project Structure
|
|
239
|
+
|
|
240
|
+
```
|
|
241
|
+
src/
|
|
242
|
+
├── index.ts # Server entry point, tool registration
|
|
243
|
+
├── api-client.ts # HTTP client for Peec.ai Customer API
|
|
244
|
+
├── types.ts # TypeScript interfaces for API responses
|
|
245
|
+
├── util.ts # Shared validation, date handling, MCP response helpers
|
|
246
|
+
├── prompts.ts # MCP prompt templates (guided workflows)
|
|
247
|
+
└── tools/ # One file per MCP tool
|
|
248
|
+
├── projects.ts
|
|
249
|
+
├── brands.ts
|
|
250
|
+
├── prompts.ts
|
|
251
|
+
├── tags.ts
|
|
252
|
+
├── topics.ts
|
|
253
|
+
├── models.ts
|
|
254
|
+
├── chats.ts
|
|
255
|
+
├── chat-content.ts
|
|
256
|
+
├── report-brands.ts
|
|
257
|
+
├── report-domains.ts
|
|
258
|
+
└── report-urls.ts
|
|
259
|
+
scripts/ # Development and CI scripts
|
|
260
|
+
└── check-api-drift.sh
|
|
261
|
+
api-spec/ # API specification snapshots
|
|
262
|
+
└── openapi-snapshot.json
|
|
263
|
+
```
|
|
264
|
+
|
|
265
|
+
## License
|
|
266
|
+
|
|
267
|
+
[MIT](./LICENSE)
|
|
268
|
+
|
|
269
|
+
---
|
|
270
|
+
|
|
271
|
+
Built by [Tobias Hein](https://github.com/thein-art) at [artaxo](https://artaxo.com) — a digital marketing agency specializing in AI Search Optimization.
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* HTTP client for the Peec.ai Customer API.
|
|
3
|
+
* Handles authentication, query parameters, timeouts, and error formatting.
|
|
4
|
+
*/
|
|
5
|
+
export declare class PeecApiClient {
|
|
6
|
+
private readonly apiKey;
|
|
7
|
+
constructor(apiKey: string);
|
|
8
|
+
/** 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>;
|
|
10
|
+
/** 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>;
|
|
12
|
+
/** 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>;
|
|
14
|
+
private request;
|
|
15
|
+
/**
|
|
16
|
+
* Builds a human-readable error message from a failed API response.
|
|
17
|
+
* Tries to extract a structured message from JSON; falls back to raw text.
|
|
18
|
+
* Truncates to MAX_ERROR_LENGTH to prevent leaking large error payloads.
|
|
19
|
+
*/
|
|
20
|
+
private formatError;
|
|
21
|
+
}
|
|
@@ -0,0 +1,83 @@
|
|
|
1
|
+
const BASE_URL = "https://api.peec.ai/customer/v1";
|
|
2
|
+
const REQUEST_TIMEOUT_MS = 30_000;
|
|
3
|
+
const MAX_ERROR_LENGTH = 500;
|
|
4
|
+
/**
|
|
5
|
+
* HTTP client for the Peec.ai Customer API.
|
|
6
|
+
* Handles authentication, query parameters, timeouts, and error formatting.
|
|
7
|
+
*/
|
|
8
|
+
export class PeecApiClient {
|
|
9
|
+
apiKey;
|
|
10
|
+
constructor(apiKey) {
|
|
11
|
+
this.apiKey = apiKey;
|
|
12
|
+
}
|
|
13
|
+
/** 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
|
+
const json = await response.json();
|
|
17
|
+
return json.data;
|
|
18
|
+
}
|
|
19
|
+
/** 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
|
+
return response.json();
|
|
23
|
+
}
|
|
24
|
+
/** POST request that unwraps the `{ data: T }` envelope. Use for analytics report endpoints. */
|
|
25
|
+
async post(path, body, params) {
|
|
26
|
+
const response = await this.request(path, {
|
|
27
|
+
method: "POST",
|
|
28
|
+
params,
|
|
29
|
+
body: JSON.stringify(body),
|
|
30
|
+
extraHeaders: { "Content-Type": "application/json" },
|
|
31
|
+
});
|
|
32
|
+
const json = await response.json();
|
|
33
|
+
return json.data;
|
|
34
|
+
}
|
|
35
|
+
async request(path, options) {
|
|
36
|
+
const url = new URL(`${BASE_URL}${path}`);
|
|
37
|
+
if (options.params) {
|
|
38
|
+
for (const [key, value] of Object.entries(options.params)) {
|
|
39
|
+
if (value !== undefined && value !== null && value !== "") {
|
|
40
|
+
url.searchParams.set(key, String(value));
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
const response = await fetch(url.toString(), {
|
|
45
|
+
method: options.method,
|
|
46
|
+
headers: {
|
|
47
|
+
"X-API-Key": this.apiKey,
|
|
48
|
+
"Accept": "application/json",
|
|
49
|
+
...options.extraHeaders,
|
|
50
|
+
},
|
|
51
|
+
body: options.body,
|
|
52
|
+
signal: AbortSignal.timeout(REQUEST_TIMEOUT_MS),
|
|
53
|
+
});
|
|
54
|
+
if (!response.ok) {
|
|
55
|
+
throw new Error(await this.formatError(response));
|
|
56
|
+
}
|
|
57
|
+
return response;
|
|
58
|
+
}
|
|
59
|
+
/**
|
|
60
|
+
* Builds a human-readable error message from a failed API response.
|
|
61
|
+
* Tries to extract a structured message from JSON; falls back to raw text.
|
|
62
|
+
* Truncates to MAX_ERROR_LENGTH to prevent leaking large error payloads.
|
|
63
|
+
*/
|
|
64
|
+
async formatError(response) {
|
|
65
|
+
const text = await response.text();
|
|
66
|
+
let message;
|
|
67
|
+
try {
|
|
68
|
+
const json = JSON.parse(text);
|
|
69
|
+
message = json.message || json.error || text;
|
|
70
|
+
}
|
|
71
|
+
catch {
|
|
72
|
+
message = text;
|
|
73
|
+
}
|
|
74
|
+
if (typeof message !== "string") {
|
|
75
|
+
message = JSON.stringify(message);
|
|
76
|
+
}
|
|
77
|
+
if (message.length > MAX_ERROR_LENGTH) {
|
|
78
|
+
message = message.slice(0, MAX_ERROR_LENGTH) + "…";
|
|
79
|
+
}
|
|
80
|
+
return `Peec API error ${response.status}: ${message}`;
|
|
81
|
+
}
|
|
82
|
+
}
|
|
83
|
+
//# sourceMappingURL=api-client.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"api-client.js","sourceRoot":"","sources":["../src/api-client.ts"],"names":[],"mappings":"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"}
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
/**
|
|
3
|
+
* Peec.ai MCP Server
|
|
4
|
+
*
|
|
5
|
+
* Exposes the Peec.ai Customer API as MCP tools for AI Search Analytics —
|
|
6
|
+
* brand visibility, sentiment, citations, and domain/URL analysis across
|
|
7
|
+
* AI models like ChatGPT and Perplexity.
|
|
8
|
+
*/
|
|
9
|
+
export {};
|
package/dist/index.js
ADDED
|
@@ -0,0 +1,79 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
/**
|
|
3
|
+
* Peec.ai MCP Server
|
|
4
|
+
*
|
|
5
|
+
* Exposes the Peec.ai Customer API as MCP tools for AI Search Analytics —
|
|
6
|
+
* brand visibility, sentiment, citations, and domain/URL analysis across
|
|
7
|
+
* AI models like ChatGPT and Perplexity.
|
|
8
|
+
*/
|
|
9
|
+
import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
|
|
10
|
+
import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js";
|
|
11
|
+
import { PeecApiClient } from "./api-client.js";
|
|
12
|
+
import { registerProjectsTool } from "./tools/projects.js";
|
|
13
|
+
import { registerBrandsTool } from "./tools/brands.js";
|
|
14
|
+
import { registerPromptsTool } from "./tools/prompts.js";
|
|
15
|
+
import { registerTagsTool } from "./tools/tags.js";
|
|
16
|
+
import { registerTopicsTool } from "./tools/topics.js";
|
|
17
|
+
import { registerModelsTool } from "./tools/models.js";
|
|
18
|
+
import { registerChatsTool } from "./tools/chats.js";
|
|
19
|
+
import { registerChatContentTool } from "./tools/chat-content.js";
|
|
20
|
+
import { registerBrandsReportTool } from "./tools/report-brands.js";
|
|
21
|
+
import { registerDomainsReportTool } from "./tools/report-domains.js";
|
|
22
|
+
import { registerUrlsReportTool } from "./tools/report-urls.js";
|
|
23
|
+
import { registerPromptTemplates } from "./prompts.js";
|
|
24
|
+
const apiKey = process.env.PEECAI_API_KEY;
|
|
25
|
+
if (!apiKey) {
|
|
26
|
+
console.error("PEECAI_API_KEY environment variable is required");
|
|
27
|
+
process.exit(1);
|
|
28
|
+
}
|
|
29
|
+
const client = new PeecApiClient(apiKey);
|
|
30
|
+
const server = new McpServer({
|
|
31
|
+
name: "peecai",
|
|
32
|
+
version: "0.2.0",
|
|
33
|
+
});
|
|
34
|
+
// Register tools
|
|
35
|
+
registerProjectsTool(server, client);
|
|
36
|
+
registerBrandsTool(server, client);
|
|
37
|
+
registerPromptsTool(server, client);
|
|
38
|
+
registerTagsTool(server, client);
|
|
39
|
+
registerTopicsTool(server, client);
|
|
40
|
+
registerModelsTool(server, client);
|
|
41
|
+
registerChatsTool(server, client);
|
|
42
|
+
registerChatContentTool(server, client);
|
|
43
|
+
registerBrandsReportTool(server, client);
|
|
44
|
+
registerDomainsReportTool(server, client);
|
|
45
|
+
registerUrlsReportTool(server, client);
|
|
46
|
+
// Register MCP prompts (guided workflows)
|
|
47
|
+
registerPromptTemplates(server);
|
|
48
|
+
// Register resource: projects://list
|
|
49
|
+
server.resource("projects-list", "projects://list", {
|
|
50
|
+
description: "List all available Peec.ai projects for the authenticated account.",
|
|
51
|
+
mimeType: "application/json",
|
|
52
|
+
}, async () => {
|
|
53
|
+
const projects = await client.get("/projects", { limit: 1000 });
|
|
54
|
+
return {
|
|
55
|
+
contents: [{
|
|
56
|
+
uri: "projects://list",
|
|
57
|
+
mimeType: "application/json",
|
|
58
|
+
text: JSON.stringify(projects),
|
|
59
|
+
}],
|
|
60
|
+
};
|
|
61
|
+
});
|
|
62
|
+
async function main() {
|
|
63
|
+
const transport = new StdioServerTransport();
|
|
64
|
+
await server.connect(transport);
|
|
65
|
+
console.error("Peec.ai MCP server running on stdio");
|
|
66
|
+
// Graceful shutdown
|
|
67
|
+
const shutdown = async () => {
|
|
68
|
+
console.error("Shutting down Peec.ai MCP server…");
|
|
69
|
+
await server.close();
|
|
70
|
+
process.exit(0);
|
|
71
|
+
};
|
|
72
|
+
process.on("SIGINT", shutdown);
|
|
73
|
+
process.on("SIGTERM", shutdown);
|
|
74
|
+
}
|
|
75
|
+
main().catch((e) => {
|
|
76
|
+
console.error("Fatal error:", e);
|
|
77
|
+
process.exit(1);
|
|
78
|
+
});
|
|
79
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
|
package/dist/prompts.js
ADDED
|
@@ -0,0 +1,100 @@
|
|
|
1
|
+
import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
|
|
2
|
+
import { z } from "zod";
|
|
3
|
+
/** Registers guided workflow prompts for common Peec.ai analytics tasks. */
|
|
4
|
+
export function registerPromptTemplates(server) {
|
|
5
|
+
server.prompt("brand-visibility-analysis", "Analyze brand visibility, sentiment, and position across AI models for a project.", {
|
|
6
|
+
project_id: z.string().describe("Project ID (uses PEECAI_PROJECT_ID env if omitted)").optional(),
|
|
7
|
+
period: z.enum(["7d", "28d", "90d"]).default("28d").describe("Analysis period"),
|
|
8
|
+
}, ({ project_id, period }) => {
|
|
9
|
+
const days = { "7d": 7, "28d": 28, "90d": 90 }[period];
|
|
10
|
+
const endDate = new Date().toISOString().slice(0, 10);
|
|
11
|
+
const startDate = new Date(Date.now() - days * 86_400_000).toISOString().slice(0, 10);
|
|
12
|
+
const projectClause = project_id ? ` for project ${project_id}` : "";
|
|
13
|
+
return {
|
|
14
|
+
messages: [{
|
|
15
|
+
role: "user",
|
|
16
|
+
content: {
|
|
17
|
+
type: "text",
|
|
18
|
+
text: [
|
|
19
|
+
`Perform a brand visibility analysis${projectClause} for the period ${startDate} to ${endDate}.`,
|
|
20
|
+
"",
|
|
21
|
+
"Steps:",
|
|
22
|
+
`1. Use get_brands_report with start_date="${startDate}", end_date="${endDate}" to get overall brand metrics.`,
|
|
23
|
+
`2. Use get_brands_report with dimensions=["model_id"] to break down visibility by AI model.`,
|
|
24
|
+
"3. Use list_brands and list_models to resolve IDs to names.",
|
|
25
|
+
"",
|
|
26
|
+
"Provide:",
|
|
27
|
+
"- A summary table of all brands with visibility, sentiment, and position",
|
|
28
|
+
"- Per-model breakdown highlighting where each brand performs best/worst",
|
|
29
|
+
"- Key insights and recommendations for improving AI visibility",
|
|
30
|
+
].join("\n"),
|
|
31
|
+
},
|
|
32
|
+
}],
|
|
33
|
+
};
|
|
34
|
+
});
|
|
35
|
+
server.prompt("competitive-gap-analysis", "Compare own brand vs competitors — identify visibility gaps across prompts and models.", {
|
|
36
|
+
project_id: z.string().describe("Project ID (uses PEECAI_PROJECT_ID env if omitted)").optional(),
|
|
37
|
+
period: z.enum(["7d", "28d", "90d"]).default("28d").describe("Analysis period"),
|
|
38
|
+
}, ({ project_id, period }) => {
|
|
39
|
+
const days = { "7d": 7, "28d": 28, "90d": 90 }[period];
|
|
40
|
+
const endDate = new Date().toISOString().slice(0, 10);
|
|
41
|
+
const startDate = new Date(Date.now() - days * 86_400_000).toISOString().slice(0, 10);
|
|
42
|
+
const projectClause = project_id ? ` for project ${project_id}` : "";
|
|
43
|
+
return {
|
|
44
|
+
messages: [{
|
|
45
|
+
role: "user",
|
|
46
|
+
content: {
|
|
47
|
+
type: "text",
|
|
48
|
+
text: [
|
|
49
|
+
`Perform a competitive gap analysis${projectClause} for the period ${startDate} to ${endDate}.`,
|
|
50
|
+
"",
|
|
51
|
+
"Steps:",
|
|
52
|
+
"1. Use list_brands to identify own brand vs competitor brands.",
|
|
53
|
+
`2. Use get_brands_report with dimensions=["prompt_id"] to see per-prompt visibility.`,
|
|
54
|
+
`3. Use get_brands_report with dimensions=["model_id"] to see per-model visibility.`,
|
|
55
|
+
"4. Use list_prompts to resolve prompt IDs to actual search queries.",
|
|
56
|
+
"",
|
|
57
|
+
"Provide:",
|
|
58
|
+
"- Side-by-side comparison table: own brand vs each competitor",
|
|
59
|
+
"- Top prompts where competitors outperform the own brand (visibility gaps)",
|
|
60
|
+
"- Models where the own brand underperforms relative to competitors",
|
|
61
|
+
"- Actionable recommendations to close the top gaps",
|
|
62
|
+
].join("\n"),
|
|
63
|
+
},
|
|
64
|
+
}],
|
|
65
|
+
};
|
|
66
|
+
});
|
|
67
|
+
server.prompt("ai-search-citation-report", "Analyze which URLs and domains get cited in AI responses — find content optimization opportunities.", {
|
|
68
|
+
project_id: z.string().describe("Project ID (uses PEECAI_PROJECT_ID env if omitted)").optional(),
|
|
69
|
+
period: z.enum(["7d", "28d", "90d"]).default("28d").describe("Analysis period"),
|
|
70
|
+
}, ({ project_id, period }) => {
|
|
71
|
+
const days = { "7d": 7, "28d": 28, "90d": 90 }[period];
|
|
72
|
+
const endDate = new Date().toISOString().slice(0, 10);
|
|
73
|
+
const startDate = new Date(Date.now() - days * 86_400_000).toISOString().slice(0, 10);
|
|
74
|
+
const projectClause = project_id ? ` for project ${project_id}` : "";
|
|
75
|
+
return {
|
|
76
|
+
messages: [{
|
|
77
|
+
role: "user",
|
|
78
|
+
content: {
|
|
79
|
+
type: "text",
|
|
80
|
+
text: [
|
|
81
|
+
`Generate an AI search citation report${projectClause} for the period ${startDate} to ${endDate}.`,
|
|
82
|
+
"",
|
|
83
|
+
"Steps:",
|
|
84
|
+
`1. Use get_domains_report with start_date="${startDate}", end_date="${endDate}" to see top cited domains.`,
|
|
85
|
+
"2. Use get_domains_report with classification filter to compare OWN vs EDITORIAL vs COMPETITOR domains.",
|
|
86
|
+
`3. Use get_urls_report with start_date="${startDate}", end_date="${endDate}" to find top cited URLs.`,
|
|
87
|
+
"4. Use get_urls_report with classification filter for ARTICLE and HOW_TO_GUIDE to find editorial opportunities.",
|
|
88
|
+
"",
|
|
89
|
+
"Provide:",
|
|
90
|
+
"- Top 20 most-cited domains with classification and usage rate",
|
|
91
|
+
"- Own domain performance vs editorial and competitor domains",
|
|
92
|
+
"- Top 20 most-cited URLs with titles and citation counts",
|
|
93
|
+
"- Content recommendations: which types of pages get cited most, and what the brand should create",
|
|
94
|
+
].join("\n"),
|
|
95
|
+
},
|
|
96
|
+
}],
|
|
97
|
+
};
|
|
98
|
+
});
|
|
99
|
+
}
|
|
100
|
+
//# sourceMappingURL=prompts.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"prompts.js","sourceRoot":"","sources":["../src/prompts.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,4 @@
|
|
|
1
|
+
import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
|
|
2
|
+
import { PeecApiClient } from "../api-client.js";
|
|
3
|
+
/** Registers the list_brands tool for retrieving tracked brands and their domains. */
|
|
4
|
+
export declare function registerBrandsTool(server: McpServer, client: PeecApiClient): void;
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
|
|
2
|
+
import { z } from "zod";
|
|
3
|
+
import { PeecApiClient } from "../api-client.js";
|
|
4
|
+
import { requireProjectId, summaryForList, toolResult, toolError } from "../util.js";
|
|
5
|
+
/** Registers the list_brands tool for retrieving tracked brands and their domains. */
|
|
6
|
+
export function registerBrandsTool(server, client) {
|
|
7
|
+
server.tool("list_brands", "List tracked brands for a Peec.ai project. Returns brand IDs, names, and associated domains.", {
|
|
8
|
+
project_id: z.string().describe("Project ID (uses PEECAI_PROJECT_ID env if omitted). Call list_projects to find IDs.").optional(),
|
|
9
|
+
limit: z.number().min(1).max(10000).default(1000).describe("Max results (1-10000)").optional(),
|
|
10
|
+
offset: z.number().min(0).default(0).describe("Results to skip").optional(),
|
|
11
|
+
}, async ({ project_id, limit, offset }) => {
|
|
12
|
+
try {
|
|
13
|
+
const data = await client.get("/brands", {
|
|
14
|
+
project_id: requireProjectId(project_id),
|
|
15
|
+
limit,
|
|
16
|
+
offset,
|
|
17
|
+
});
|
|
18
|
+
return toolResult({ _summary: summaryForList("brands", data), brands: data });
|
|
19
|
+
}
|
|
20
|
+
catch (e) {
|
|
21
|
+
return toolError(e);
|
|
22
|
+
}
|
|
23
|
+
});
|
|
24
|
+
}
|
|
25
|
+
//# sourceMappingURL=brands.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"brands.js","sourceRoot":"","sources":["../../src/tools/brands.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,MAAM,yCAAyC,CAAC;AACpE,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AACxB,OAAO,EAAE,aAAa,EAAE,MAAM,kBAAkB,CAAC;AACjD,OAAO,EAAE,gBAAgB,EAAE,cAAc,EAAE,UAAU,EAAE,SAAS,EAAE,MAAM,YAAY,CAAC;AAGrF,sFAAsF;AACtF,MAAM,UAAU,kBAAkB,CAAC,MAAiB,EAAE,MAAqB;IACzE,MAAM,CAAC,IAAI,CACT,aAAa,EACb,8FAA8F,EAC9F;QACE,UAAU,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,CAAC,qFAAqF,CAAC,CAAC,QAAQ,EAAE;QACjI,KAAK,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,KAAK,CAAC,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC,QAAQ,CAAC,uBAAuB,CAAC,CAAC,QAAQ,EAAE;QAC9F,MAAM,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC,QAAQ,CAAC,iBAAiB,CAAC,CAAC,QAAQ,EAAE;KAC5E,EACD,KAAK,EAAE,EAAE,UAAU,EAAE,KAAK,EAAE,MAAM,EAAE,EAAE,EAAE;QACtC,IAAI,CAAC;YACH,MAAM,IAAI,GAAG,MAAM,MAAM,CAAC,GAAG,CAAU,SAAS,EAAE;gBAChD,UAAU,EAAE,gBAAgB,CAAC,UAAU,CAAC;gBACxC,KAAK;gBACL,MAAM;aACP,CAAC,CAAC;YACH,OAAO,UAAU,CAAC,EAAE,QAAQ,EAAE,cAAc,CAAC,QAAQ,EAAE,IAAI,CAAC,EAAE,MAAM,EAAE,IAAI,EAAE,CAAC,CAAC;QAChF,CAAC;QAAC,OAAO,CAAC,EAAE,CAAC;YACX,OAAO,SAAS,CAAC,CAAC,CAAC,CAAC;QACtB,CAAC;IACH,CAAC,CACF,CAAC;AACJ,CAAC"}
|
|
@@ -0,0 +1,4 @@
|
|
|
1
|
+
import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
|
|
2
|
+
import { PeecApiClient } from "../api-client.js";
|
|
3
|
+
/** Registers the get_chat_content tool for retrieving full chat details. */
|
|
4
|
+
export declare function registerChatContentTool(server: McpServer, client: PeecApiClient): void;
|