@chorus-research/mcp 0.1.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/README.md +126 -0
- package/dist/client.d.ts +162 -0
- package/dist/client.d.ts.map +1 -0
- package/dist/client.js +86 -0
- package/dist/client.js.map +1 -0
- package/dist/index.d.ts +3 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +48 -0
- package/dist/index.js.map +1 -0
- package/dist/prompts/design-survey.d.ts +3 -0
- package/dist/prompts/design-survey.d.ts.map +1 -0
- package/dist/prompts/design-survey.js +98 -0
- package/dist/prompts/design-survey.js.map +1 -0
- package/dist/prompts/launch-checklist.d.ts +3 -0
- package/dist/prompts/launch-checklist.d.ts.map +1 -0
- package/dist/prompts/launch-checklist.js +74 -0
- package/dist/prompts/launch-checklist.js.map +1 -0
- package/dist/resources/audiences.d.ts +4 -0
- package/dist/resources/audiences.d.ts.map +1 -0
- package/dist/resources/audiences.js +13 -0
- package/dist/resources/audiences.js.map +1 -0
- package/dist/resources/pricing.d.ts +4 -0
- package/dist/resources/pricing.d.ts.map +1 -0
- package/dist/resources/pricing.js +13 -0
- package/dist/resources/pricing.js.map +1 -0
- package/dist/tools/audiences.d.ts +4 -0
- package/dist/tools/audiences.d.ts.map +1 -0
- package/dist/tools/audiences.js +27 -0
- package/dist/tools/audiences.js.map +1 -0
- package/dist/tools/launch.d.ts +4 -0
- package/dist/tools/launch.d.ts.map +1 -0
- package/dist/tools/launch.js +87 -0
- package/dist/tools/launch.js.map +1 -0
- package/dist/tools/pricing.d.ts +4 -0
- package/dist/tools/pricing.d.ts.map +1 -0
- package/dist/tools/pricing.js +38 -0
- package/dist/tools/pricing.js.map +1 -0
- package/dist/tools/responses.d.ts +4 -0
- package/dist/tools/responses.d.ts.map +1 -0
- package/dist/tools/responses.js +40 -0
- package/dist/tools/responses.js.map +1 -0
- package/dist/tools/surveys.d.ts +4 -0
- package/dist/tools/surveys.d.ts.map +1 -0
- package/dist/tools/surveys.js +74 -0
- package/dist/tools/surveys.js.map +1 -0
- package/package.json +42 -0
package/README.md
ADDED
|
@@ -0,0 +1,126 @@
|
|
|
1
|
+
# @chorus-research/mcp
|
|
2
|
+
|
|
3
|
+
MCP server for the [Chorus Research](https://chorusresearch.com) survey platform — create surveys, launch them to targeted audiences, and collect responses, all from your AI agent.
|
|
4
|
+
|
|
5
|
+
Built on the [Model Context Protocol](https://modelcontextprotocol.io).
|
|
6
|
+
|
|
7
|
+
## Quick Start
|
|
8
|
+
|
|
9
|
+
### 1. Get an API key
|
|
10
|
+
|
|
11
|
+
Sign up at [chorusresearch.com](https://chorusresearch.com) and generate an API key from your dashboard.
|
|
12
|
+
|
|
13
|
+
### 2. Add to your MCP client
|
|
14
|
+
|
|
15
|
+
**Claude Code (`.mcp.json`)**:
|
|
16
|
+
|
|
17
|
+
```json
|
|
18
|
+
{
|
|
19
|
+
"mcpServers": {
|
|
20
|
+
"chorus-research": {
|
|
21
|
+
"command": "npx",
|
|
22
|
+
"args": ["@chorus-research/mcp"],
|
|
23
|
+
"env": {
|
|
24
|
+
"CHORUS_API_KEY": "your-api-key"
|
|
25
|
+
}
|
|
26
|
+
}
|
|
27
|
+
}
|
|
28
|
+
}
|
|
29
|
+
```
|
|
30
|
+
|
|
31
|
+
**Claude Desktop (`claude_desktop_config.json`)**:
|
|
32
|
+
|
|
33
|
+
```json
|
|
34
|
+
{
|
|
35
|
+
"mcpServers": {
|
|
36
|
+
"chorus-research": {
|
|
37
|
+
"command": "npx",
|
|
38
|
+
"args": ["@chorus-research/mcp"],
|
|
39
|
+
"env": {
|
|
40
|
+
"CHORUS_API_KEY": "your-api-key"
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
```
|
|
46
|
+
|
|
47
|
+
## Tools
|
|
48
|
+
|
|
49
|
+
The server exposes 10 tools across surveys, audiences, pricing, launch, and responses.
|
|
50
|
+
|
|
51
|
+
### Surveys
|
|
52
|
+
|
|
53
|
+
| Tool | Description | Key Parameters |
|
|
54
|
+
|------|-------------|----------------|
|
|
55
|
+
| `list_surveys` | List surveys with optional filtering and pagination | `status?`, `page?`, `pageSize?`, `sort?`, `order?` |
|
|
56
|
+
| `get_survey` | Get full survey details including the JSON definition | `surveyId` |
|
|
57
|
+
| `create_survey` | Create a new survey draft | `name`, `survey` (JSON), `targetCompletes`, `description?` |
|
|
58
|
+
|
|
59
|
+
### Audiences
|
|
60
|
+
|
|
61
|
+
| Tool | Description | Key Parameters |
|
|
62
|
+
|------|-------------|----------------|
|
|
63
|
+
| `list_audiences` | List all available audience segments with costs and targeting criteria | _(none)_ |
|
|
64
|
+
| `get_audience` | Get details for a specific audience segment | `audienceId` |
|
|
65
|
+
|
|
66
|
+
### Pricing
|
|
67
|
+
|
|
68
|
+
| Tool | Description | Key Parameters |
|
|
69
|
+
|------|-------------|----------------|
|
|
70
|
+
| `estimate_cost` | Calculate launch cost (costPerResponse x targetCompletes) | `audienceId`, `targetCompletes`, `projectId?` |
|
|
71
|
+
| `get_pricing_config` | Get current cost-per-response and currency | _(none)_ |
|
|
72
|
+
|
|
73
|
+
### Launch (two-step)
|
|
74
|
+
|
|
75
|
+
| Tool | Description | Key Parameters |
|
|
76
|
+
|------|-------------|----------------|
|
|
77
|
+
| `launch_survey` | Launch a survey to collect responses | See below |
|
|
78
|
+
| `get_survey_status` | Real-time fielding status (completes, progress %, ETA) | `surveyId` |
|
|
79
|
+
|
|
80
|
+
**`launch_survey` is a two-step process** to prevent accidental charges:
|
|
81
|
+
|
|
82
|
+
1. **Estimate** — call with `surveyId`, `audienceId`, and `targetCompletes`. Returns a cost estimate and a `confirmToken` (valid 5 minutes).
|
|
83
|
+
2. **Confirm** — call again with `surveyId` and the `confirmToken` to execute the launch and charge payment.
|
|
84
|
+
|
|
85
|
+
```
|
|
86
|
+
# Step 1: Get estimate
|
|
87
|
+
launch_survey(surveyId, audienceId="genpop", targetCompletes=100)
|
|
88
|
+
# → { step: "estimate", estimatedCost: 100, confirmToken: "tok_...", expiresAt: "..." }
|
|
89
|
+
|
|
90
|
+
# Step 2: Confirm (triggers real charges)
|
|
91
|
+
launch_survey(surveyId, confirmToken="tok_...")
|
|
92
|
+
# → { step: "confirmed", success: true, amountCharged: 100 }
|
|
93
|
+
```
|
|
94
|
+
|
|
95
|
+
### Responses
|
|
96
|
+
|
|
97
|
+
| Tool | Description | Key Parameters |
|
|
98
|
+
|------|-------------|----------------|
|
|
99
|
+
| `get_responses` | Export response data with pagination | `surveyId`, `page?`, `pageSize?`, `status?`, `includeDuplicates?` |
|
|
100
|
+
|
|
101
|
+
Response metadata includes device info (userAgent, screenSize, timezone), geographic data (city, state, country), and provider demographics when available. Duplicates are excluded by default.
|
|
102
|
+
|
|
103
|
+
## Resources
|
|
104
|
+
|
|
105
|
+
| URI | Name | Description |
|
|
106
|
+
|-----|------|-------------|
|
|
107
|
+
| `chorus://audiences` | Audience Catalog | Full catalog of audience segments with targeting, costs, and fielding times |
|
|
108
|
+
| `chorus://pricing/config` | Pricing Configuration | Current cost-per-response and currency |
|
|
109
|
+
|
|
110
|
+
## Prompts
|
|
111
|
+
|
|
112
|
+
| Name | Description | Arguments |
|
|
113
|
+
|------|-------------|-----------|
|
|
114
|
+
| `design_survey` | Guides survey creation with best practices | `topic` (required), `audience?`, `numQuestions?` |
|
|
115
|
+
| `launch_checklist` | Pre-launch validation checklist with cost review | `surveyId` (required) |
|
|
116
|
+
|
|
117
|
+
## Configuration
|
|
118
|
+
|
|
119
|
+
| Environment Variable | Description | Default |
|
|
120
|
+
|---------------------|-------------|---------|
|
|
121
|
+
| `CHORUS_API_KEY` | API key for authentication (required) | _(none)_ |
|
|
122
|
+
| `CHORUS_API_BASE_URL` | Base URL for the Chorus Research API | `https://api.chorusresearch.io` |
|
|
123
|
+
|
|
124
|
+
## Requirements
|
|
125
|
+
|
|
126
|
+
- Node.js >= 20
|
package/dist/client.d.ts
ADDED
|
@@ -0,0 +1,162 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Typed HTTP client wrapping the Chorus Research Public API.
|
|
3
|
+
*
|
|
4
|
+
* Reads CHORUS_API_KEY and CHORUS_API_BASE_URL from the environment.
|
|
5
|
+
*/
|
|
6
|
+
export interface Audience {
|
|
7
|
+
id: string;
|
|
8
|
+
name: string;
|
|
9
|
+
description: string;
|
|
10
|
+
costPerResponse: number;
|
|
11
|
+
minTargetCompletes: number;
|
|
12
|
+
maxTargetCompletes: number;
|
|
13
|
+
averageLengthOfInterview: number;
|
|
14
|
+
targeting: {
|
|
15
|
+
age_min: number;
|
|
16
|
+
age_max: number;
|
|
17
|
+
country: string;
|
|
18
|
+
};
|
|
19
|
+
estimatedFieldingTime: Record<string, string>;
|
|
20
|
+
}
|
|
21
|
+
export interface Survey {
|
|
22
|
+
id: string;
|
|
23
|
+
name: string;
|
|
24
|
+
survey: Record<string, unknown>;
|
|
25
|
+
targetCompletes: number;
|
|
26
|
+
description?: string;
|
|
27
|
+
status: "draft" | "live" | "complete" | "cancelled";
|
|
28
|
+
createdAt: string;
|
|
29
|
+
updatedAt: string;
|
|
30
|
+
}
|
|
31
|
+
export interface Pagination {
|
|
32
|
+
page: number;
|
|
33
|
+
pageSize: number;
|
|
34
|
+
total: number;
|
|
35
|
+
totalPages: number;
|
|
36
|
+
}
|
|
37
|
+
export interface PricingEstimate {
|
|
38
|
+
audienceId: string;
|
|
39
|
+
targetCompletes: number;
|
|
40
|
+
baseCostPerComplete: number;
|
|
41
|
+
subtotal: number;
|
|
42
|
+
total: number;
|
|
43
|
+
currency: string;
|
|
44
|
+
}
|
|
45
|
+
export interface PricingConfig {
|
|
46
|
+
costPerResponse: number;
|
|
47
|
+
currency: string;
|
|
48
|
+
}
|
|
49
|
+
export interface LaunchEstimate {
|
|
50
|
+
estimatedCost: number;
|
|
51
|
+
breakdown: PricingEstimate;
|
|
52
|
+
confirmToken: string;
|
|
53
|
+
expiresAt: string;
|
|
54
|
+
}
|
|
55
|
+
export interface LaunchConfirmation {
|
|
56
|
+
success: boolean;
|
|
57
|
+
publishedSurveyId: string;
|
|
58
|
+
workflowId: string;
|
|
59
|
+
paymentIntentId: string;
|
|
60
|
+
amountCharged: number;
|
|
61
|
+
currency: string;
|
|
62
|
+
targetCompletes: number;
|
|
63
|
+
}
|
|
64
|
+
export interface SurveyStatus {
|
|
65
|
+
projectId: string;
|
|
66
|
+
publishedSurveyId: string | null;
|
|
67
|
+
status: "draft" | "live" | "complete" | "cancelled";
|
|
68
|
+
completes: number;
|
|
69
|
+
target: number;
|
|
70
|
+
progress: number;
|
|
71
|
+
lastUpdated: string;
|
|
72
|
+
estimatedCompletion: string | null;
|
|
73
|
+
message?: string;
|
|
74
|
+
}
|
|
75
|
+
export interface SurveyResponse {
|
|
76
|
+
id: string;
|
|
77
|
+
publishedSurveyId: string;
|
|
78
|
+
responseData: Record<string, unknown>;
|
|
79
|
+
metadata: {
|
|
80
|
+
rdud?: string;
|
|
81
|
+
completedAt?: string;
|
|
82
|
+
supplier?: string;
|
|
83
|
+
demographics?: Record<string, unknown>;
|
|
84
|
+
start_time?: string;
|
|
85
|
+
end_time?: string;
|
|
86
|
+
generated_at?: string;
|
|
87
|
+
userAgent?: string;
|
|
88
|
+
language?: string;
|
|
89
|
+
screenSize?: string;
|
|
90
|
+
timezone?: string;
|
|
91
|
+
city?: string;
|
|
92
|
+
state?: string;
|
|
93
|
+
region?: string;
|
|
94
|
+
country?: string;
|
|
95
|
+
};
|
|
96
|
+
status: "complete" | "partial" | "incomplete";
|
|
97
|
+
supplier: string | null;
|
|
98
|
+
createdAt: string;
|
|
99
|
+
completedAt: string;
|
|
100
|
+
}
|
|
101
|
+
export interface ApiError {
|
|
102
|
+
error: string;
|
|
103
|
+
message: string;
|
|
104
|
+
code: string;
|
|
105
|
+
}
|
|
106
|
+
export declare class ChorusApiClient {
|
|
107
|
+
private baseUrl;
|
|
108
|
+
private apiKey;
|
|
109
|
+
constructor(opts?: {
|
|
110
|
+
baseUrl?: string;
|
|
111
|
+
apiKey?: string;
|
|
112
|
+
});
|
|
113
|
+
private headers;
|
|
114
|
+
private request;
|
|
115
|
+
listAudiences(): Promise<{
|
|
116
|
+
audiences: Audience[];
|
|
117
|
+
count: number;
|
|
118
|
+
}>;
|
|
119
|
+
getAudience(id: string): Promise<Audience>;
|
|
120
|
+
estimateCost(params: {
|
|
121
|
+
audienceId: string;
|
|
122
|
+
targetCompletes: number;
|
|
123
|
+
projectId?: string;
|
|
124
|
+
}): Promise<PricingEstimate>;
|
|
125
|
+
getPricingConfig(): Promise<PricingConfig>;
|
|
126
|
+
createSurvey(params: {
|
|
127
|
+
name: string;
|
|
128
|
+
survey: Record<string, unknown>;
|
|
129
|
+
targetCompletes: number;
|
|
130
|
+
description?: string;
|
|
131
|
+
}): Promise<Survey>;
|
|
132
|
+
listSurveys(params?: {
|
|
133
|
+
status?: string;
|
|
134
|
+
page?: number;
|
|
135
|
+
pageSize?: number;
|
|
136
|
+
sort?: string;
|
|
137
|
+
order?: string;
|
|
138
|
+
}): Promise<{
|
|
139
|
+
surveys: Survey[];
|
|
140
|
+
pagination: Pagination;
|
|
141
|
+
}>;
|
|
142
|
+
getSurvey(id: string): Promise<Survey>;
|
|
143
|
+
launchEstimate(surveyId: string, params: {
|
|
144
|
+
audienceId: string;
|
|
145
|
+
targetCompletes: number;
|
|
146
|
+
}): Promise<LaunchEstimate>;
|
|
147
|
+
launchConfirm(surveyId: string, params: {
|
|
148
|
+
confirmToken: string;
|
|
149
|
+
paymentMethodId?: string;
|
|
150
|
+
}): Promise<LaunchConfirmation>;
|
|
151
|
+
getSurveyStatus(surveyId: string): Promise<SurveyStatus>;
|
|
152
|
+
getResponses(surveyId: string, params?: {
|
|
153
|
+
page?: number;
|
|
154
|
+
pageSize?: number;
|
|
155
|
+
status?: string;
|
|
156
|
+
includeDuplicates?: boolean;
|
|
157
|
+
}): Promise<{
|
|
158
|
+
responses: SurveyResponse[];
|
|
159
|
+
pagination: Pagination;
|
|
160
|
+
}>;
|
|
161
|
+
}
|
|
162
|
+
//# sourceMappingURL=client.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"client.d.ts","sourceRoot":"","sources":["../src/client.ts"],"names":[],"mappings":"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"}
|
package/dist/client.js
ADDED
|
@@ -0,0 +1,86 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Typed HTTP client wrapping the Chorus Research Public API.
|
|
3
|
+
*
|
|
4
|
+
* Reads CHORUS_API_KEY and CHORUS_API_BASE_URL from the environment.
|
|
5
|
+
*/
|
|
6
|
+
// ── Client ────────────────────────────────────────────────────────
|
|
7
|
+
export class ChorusApiClient {
|
|
8
|
+
baseUrl;
|
|
9
|
+
apiKey;
|
|
10
|
+
constructor(opts) {
|
|
11
|
+
this.baseUrl = (opts?.baseUrl ??
|
|
12
|
+
process.env.CHORUS_API_BASE_URL ??
|
|
13
|
+
"https://api.chorusresearch.io").replace(/\/$/, "");
|
|
14
|
+
this.apiKey = opts?.apiKey ?? process.env.CHORUS_API_KEY ?? "";
|
|
15
|
+
}
|
|
16
|
+
// ── Internals ──────────────────────────────────────────────────
|
|
17
|
+
headers() {
|
|
18
|
+
const h = {
|
|
19
|
+
"Content-Type": "application/json",
|
|
20
|
+
Accept: "application/json",
|
|
21
|
+
};
|
|
22
|
+
if (this.apiKey) {
|
|
23
|
+
h["Authorization"] = `Bearer ${this.apiKey}`;
|
|
24
|
+
}
|
|
25
|
+
return h;
|
|
26
|
+
}
|
|
27
|
+
async request(method, path, body, query) {
|
|
28
|
+
const url = new URL(`${this.baseUrl}${path}`);
|
|
29
|
+
if (query) {
|
|
30
|
+
for (const [k, v] of Object.entries(query)) {
|
|
31
|
+
if (v !== undefined)
|
|
32
|
+
url.searchParams.set(k, String(v));
|
|
33
|
+
}
|
|
34
|
+
}
|
|
35
|
+
const res = await fetch(url.toString(), {
|
|
36
|
+
method,
|
|
37
|
+
headers: this.headers(),
|
|
38
|
+
body: body ? JSON.stringify(body) : undefined,
|
|
39
|
+
});
|
|
40
|
+
const json = await res.json();
|
|
41
|
+
if (!res.ok) {
|
|
42
|
+
const err = json;
|
|
43
|
+
throw new Error(`API ${res.status}: ${err.message ?? err.error ?? "Unknown error"} (${err.code ?? "NO_CODE"})`);
|
|
44
|
+
}
|
|
45
|
+
return json;
|
|
46
|
+
}
|
|
47
|
+
// ── Audiences ──────────────────────────────────────────────────
|
|
48
|
+
async listAudiences() {
|
|
49
|
+
return this.request("GET", "/audiences");
|
|
50
|
+
}
|
|
51
|
+
async getAudience(id) {
|
|
52
|
+
return this.request("GET", `/audiences/${encodeURIComponent(id)}`);
|
|
53
|
+
}
|
|
54
|
+
// ── Pricing ────────────────────────────────────────────────────
|
|
55
|
+
async estimateCost(params) {
|
|
56
|
+
return this.request("POST", "/pricing/estimate", params);
|
|
57
|
+
}
|
|
58
|
+
async getPricingConfig() {
|
|
59
|
+
return this.request("GET", "/pricing/config");
|
|
60
|
+
}
|
|
61
|
+
// ── Surveys ────────────────────────────────────────────────────
|
|
62
|
+
async createSurvey(params) {
|
|
63
|
+
return this.request("POST", "/surveys", params);
|
|
64
|
+
}
|
|
65
|
+
async listSurveys(params) {
|
|
66
|
+
return this.request("GET", "/surveys", undefined, params);
|
|
67
|
+
}
|
|
68
|
+
async getSurvey(id) {
|
|
69
|
+
return this.request("GET", `/surveys/${encodeURIComponent(id)}`);
|
|
70
|
+
}
|
|
71
|
+
// ── Launch ─────────────────────────────────────────────────────
|
|
72
|
+
async launchEstimate(surveyId, params) {
|
|
73
|
+
return this.request("POST", `/surveys/${encodeURIComponent(surveyId)}/launch`, params);
|
|
74
|
+
}
|
|
75
|
+
async launchConfirm(surveyId, params) {
|
|
76
|
+
return this.request("POST", `/surveys/${encodeURIComponent(surveyId)}/launch/confirm`, params);
|
|
77
|
+
}
|
|
78
|
+
async getSurveyStatus(surveyId) {
|
|
79
|
+
return this.request("GET", `/surveys/${encodeURIComponent(surveyId)}/status`);
|
|
80
|
+
}
|
|
81
|
+
// ── Responses ──────────────────────────────────────────────────
|
|
82
|
+
async getResponses(surveyId, params) {
|
|
83
|
+
return this.request("GET", `/surveys/${encodeURIComponent(surveyId)}/responses`, undefined, params);
|
|
84
|
+
}
|
|
85
|
+
}
|
|
86
|
+
//# sourceMappingURL=client.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"client.js","sourceRoot":"","sources":["../src/client.ts"],"names":[],"mappings":"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"}
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":""}
|
package/dist/index.js
ADDED
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
import { FastMCP } from "fastmcp";
|
|
3
|
+
import { ChorusApiClient } from "./client.js";
|
|
4
|
+
import { registerSurveyTools } from "./tools/surveys.js";
|
|
5
|
+
import { registerAudienceTools } from "./tools/audiences.js";
|
|
6
|
+
import { registerPricingTools } from "./tools/pricing.js";
|
|
7
|
+
import { registerLaunchTools } from "./tools/launch.js";
|
|
8
|
+
import { registerResponseTools } from "./tools/responses.js";
|
|
9
|
+
import { registerAudienceResources } from "./resources/audiences.js";
|
|
10
|
+
import { registerPricingResources } from "./resources/pricing.js";
|
|
11
|
+
import { registerDesignSurveyPrompt } from "./prompts/design-survey.js";
|
|
12
|
+
import { registerLaunchChecklistPrompt } from "./prompts/launch-checklist.js";
|
|
13
|
+
const server = new FastMCP({
|
|
14
|
+
name: "Chorus Research",
|
|
15
|
+
version: "0.1.0",
|
|
16
|
+
instructions: `Chorus Research MCP — programmatic survey creation, launch, and response collection.
|
|
17
|
+
|
|
18
|
+
## Quick Start
|
|
19
|
+
1. Use \`list_audiences\` to see available audience segments
|
|
20
|
+
2. Use \`get_pricing_config\` or \`estimate_cost\` to understand pricing
|
|
21
|
+
3. Use \`create_survey\` to create a survey draft with a JSON definition
|
|
22
|
+
4. Use \`launch_survey\` (two-step) to launch and collect responses
|
|
23
|
+
5. Use \`get_responses\` to export collected data
|
|
24
|
+
|
|
25
|
+
## Key Concepts
|
|
26
|
+
- **Audiences**: Pre-defined respondent segments (e.g., "genpop" = US adults 18+)
|
|
27
|
+
- **Two-step launch**: Launching requires an estimate step then a confirm step to prevent accidental charges
|
|
28
|
+
- **Fielding**: After launch, responses are collected automatically from the target audience
|
|
29
|
+
|
|
30
|
+
## Authentication
|
|
31
|
+
Set the CHORUS_API_KEY environment variable with your API key.`,
|
|
32
|
+
});
|
|
33
|
+
const api = new ChorusApiClient();
|
|
34
|
+
// Register tools
|
|
35
|
+
registerSurveyTools(server, api);
|
|
36
|
+
registerAudienceTools(server, api);
|
|
37
|
+
registerPricingTools(server, api);
|
|
38
|
+
registerLaunchTools(server, api);
|
|
39
|
+
registerResponseTools(server, api);
|
|
40
|
+
// Register resources
|
|
41
|
+
registerAudienceResources(server, api);
|
|
42
|
+
registerPricingResources(server, api);
|
|
43
|
+
// Register prompts
|
|
44
|
+
registerDesignSurveyPrompt(server);
|
|
45
|
+
registerLaunchChecklistPrompt(server);
|
|
46
|
+
// Start on stdio (consumer MCP clients)
|
|
47
|
+
server.start({ transportType: "stdio" });
|
|
48
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":";AACA,OAAO,EAAE,OAAO,EAAE,MAAM,SAAS,CAAC;AAClC,OAAO,EAAE,eAAe,EAAE,MAAM,aAAa,CAAC;AAC9C,OAAO,EAAE,mBAAmB,EAAE,MAAM,oBAAoB,CAAC;AACzD,OAAO,EAAE,qBAAqB,EAAE,MAAM,sBAAsB,CAAC;AAC7D,OAAO,EAAE,oBAAoB,EAAE,MAAM,oBAAoB,CAAC;AAC1D,OAAO,EAAE,mBAAmB,EAAE,MAAM,mBAAmB,CAAC;AACxD,OAAO,EAAE,qBAAqB,EAAE,MAAM,sBAAsB,CAAC;AAC7D,OAAO,EAAE,yBAAyB,EAAE,MAAM,0BAA0B,CAAC;AACrE,OAAO,EAAE,wBAAwB,EAAE,MAAM,wBAAwB,CAAC;AAClE,OAAO,EAAE,0BAA0B,EAAE,MAAM,4BAA4B,CAAC;AACxE,OAAO,EAAE,6BAA6B,EAAE,MAAM,+BAA+B,CAAC;AAE9E,MAAM,MAAM,GAAG,IAAI,OAAO,CAAC;IACzB,IAAI,EAAE,iBAAiB;IACvB,OAAO,EAAE,OAAO;IAChB,YAAY,EAAE;;;;;;;;;;;;;;;+DAe+C;CAC9D,CAAC,CAAC;AAEH,MAAM,GAAG,GAAG,IAAI,eAAe,EAAE,CAAC;AAElC,iBAAiB;AACjB,mBAAmB,CAAC,MAAM,EAAE,GAAG,CAAC,CAAC;AACjC,qBAAqB,CAAC,MAAM,EAAE,GAAG,CAAC,CAAC;AACnC,oBAAoB,CAAC,MAAM,EAAE,GAAG,CAAC,CAAC;AAClC,mBAAmB,CAAC,MAAM,EAAE,GAAG,CAAC,CAAC;AACjC,qBAAqB,CAAC,MAAM,EAAE,GAAG,CAAC,CAAC;AAEnC,qBAAqB;AACrB,yBAAyB,CAAC,MAAM,EAAE,GAAG,CAAC,CAAC;AACvC,wBAAwB,CAAC,MAAM,EAAE,GAAG,CAAC,CAAC;AAEtC,mBAAmB;AACnB,0BAA0B,CAAC,MAAM,CAAC,CAAC;AACnC,6BAA6B,CAAC,MAAM,CAAC,CAAC;AAEtC,wCAAwC;AACxC,MAAM,CAAC,KAAK,CAAC,EAAE,aAAa,EAAE,OAAO,EAAE,CAAC,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"design-survey.d.ts","sourceRoot":"","sources":["../../src/prompts/design-survey.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,SAAS,CAAC;AAEvC,wBAAgB,0BAA0B,CAAC,MAAM,EAAE,OAAO,QAmGzD"}
|
|
@@ -0,0 +1,98 @@
|
|
|
1
|
+
export function registerDesignSurveyPrompt(server) {
|
|
2
|
+
server.addPrompt({
|
|
3
|
+
name: "design_survey",
|
|
4
|
+
description: "Guide an AI agent through survey creation best practices for the Chorus Research platform. Produces a valid SurveyJS JSON definition.",
|
|
5
|
+
arguments: [
|
|
6
|
+
{
|
|
7
|
+
name: "topic",
|
|
8
|
+
description: "The research topic or objective for the survey",
|
|
9
|
+
required: true,
|
|
10
|
+
},
|
|
11
|
+
{
|
|
12
|
+
name: "audience",
|
|
13
|
+
description: 'Target audience description (e.g., "US adults 18+", "parents with young children")',
|
|
14
|
+
required: false,
|
|
15
|
+
},
|
|
16
|
+
{
|
|
17
|
+
name: "numQuestions",
|
|
18
|
+
description: "Approximate number of questions desired (default: 10)",
|
|
19
|
+
required: false,
|
|
20
|
+
},
|
|
21
|
+
],
|
|
22
|
+
async load({ topic, audience, numQuestions }) {
|
|
23
|
+
const count = numQuestions || "10";
|
|
24
|
+
const aud = audience || "general population (US adults 18+)";
|
|
25
|
+
return `You are designing a survey for the Chorus Research platform. Follow these best practices:
|
|
26
|
+
|
|
27
|
+
## Research Objective
|
|
28
|
+
${topic}
|
|
29
|
+
|
|
30
|
+
## Target Audience
|
|
31
|
+
${aud}
|
|
32
|
+
|
|
33
|
+
## Guidelines
|
|
34
|
+
|
|
35
|
+
### Survey Structure
|
|
36
|
+
- Target approximately ${count} questions
|
|
37
|
+
- Keep the survey under 15 minutes to avoid LOI cost multipliers (>15 min = 20% cost increase)
|
|
38
|
+
- Group related questions onto the same page
|
|
39
|
+
- Start with easy, engaging questions before sensitive topics
|
|
40
|
+
- Use a logical flow — general to specific
|
|
41
|
+
- Survey questions are limited to 10, server will reject more.
|
|
42
|
+
- There must be at least 1 question for a survey to launch
|
|
43
|
+
|
|
44
|
+
### Question Types Available
|
|
45
|
+
- **text**: Short open-ended (use inputType: "text", "email", "number", "date")
|
|
46
|
+
- **comment**: Long open-ended (multi-line textarea)
|
|
47
|
+
- **radiogroup**: Single-select from a list
|
|
48
|
+
- **checkbox**: Multi-select from a list
|
|
49
|
+
- **dropdown**: Single-select dropdown (good for long lists)
|
|
50
|
+
- **tagbox**: Multi-select searchable dropdown
|
|
51
|
+
- **boolean**: Yes/No toggle
|
|
52
|
+
- **rating**: Numeric or star scale
|
|
53
|
+
- **ranking**: Drag-and-drop ordering
|
|
54
|
+
|
|
55
|
+
### Best Practices
|
|
56
|
+
- Every input question should have \`"isRequired": true\` (auto-enforced at publish)
|
|
57
|
+
- Use clear, unbiased question wording
|
|
58
|
+
- Avoid double-barreled questions (asking two things at once)
|
|
59
|
+
- Include "Prefer not to answer" or "Other" options for sensitive questions
|
|
60
|
+
- Use \`visibleIf\` for conditional logic (e.g., show follow-up only if parent answer matches)
|
|
61
|
+
- Keep choice lists to 7±2 items when possible
|
|
62
|
+
- Use consistent scale directions (e.g., always low-to-high)
|
|
63
|
+
|
|
64
|
+
### Survey JSON Format
|
|
65
|
+
The output must be a valid JSON object with this structure:
|
|
66
|
+
\`\`\`json
|
|
67
|
+
{
|
|
68
|
+
"title": "Survey Title",
|
|
69
|
+
"description": "Brief description",
|
|
70
|
+
"pages": [
|
|
71
|
+
{
|
|
72
|
+
"name": "page1",
|
|
73
|
+
"title": "Page Title",
|
|
74
|
+
"elements": [
|
|
75
|
+
{
|
|
76
|
+
"type": "radiogroup",
|
|
77
|
+
"name": "q1_unique_name",
|
|
78
|
+
"title": "Question text here?",
|
|
79
|
+
"isRequired": true,
|
|
80
|
+
"choices": ["Option 1", "Option 2", "Option 3"]
|
|
81
|
+
}
|
|
82
|
+
]
|
|
83
|
+
}
|
|
84
|
+
]
|
|
85
|
+
}
|
|
86
|
+
\`\`\`
|
|
87
|
+
|
|
88
|
+
### Constraints
|
|
89
|
+
- Maximum 10 pages, 50 elements per page
|
|
90
|
+
- Maximum 5 MB total survey definition
|
|
91
|
+
- All question \`name\` fields must be unique within the survey
|
|
92
|
+
- URLs in questions must be HTTP/HTTPS
|
|
93
|
+
|
|
94
|
+
Please create the complete SurveyJS JSON for this survey, then use the \`create_survey\` tool to save it as a draft.`;
|
|
95
|
+
},
|
|
96
|
+
});
|
|
97
|
+
}
|
|
98
|
+
//# sourceMappingURL=design-survey.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"design-survey.js","sourceRoot":"","sources":["../../src/prompts/design-survey.ts"],"names":[],"mappings":"AAEA,MAAM,UAAU,0BAA0B,CAAC,MAAe;IACxD,MAAM,CAAC,SAAS,CAAC;QACf,IAAI,EAAE,eAAe;QACrB,WAAW,EACT,uIAAuI;QACzI,SAAS,EAAE;YACT;gBACE,IAAI,EAAE,OAAO;gBACb,WAAW,EAAE,gDAAgD;gBAC7D,QAAQ,EAAE,IAAI;aACf;YACD;gBACE,IAAI,EAAE,UAAU;gBAChB,WAAW,EACT,oFAAoF;gBACtF,QAAQ,EAAE,KAAK;aAChB;YACD;gBACE,IAAI,EAAE,cAAc;gBACpB,WAAW,EAAE,uDAAuD;gBACpE,QAAQ,EAAE,KAAK;aAChB;SACF;QACD,KAAK,CAAC,IAAI,CAAC,EAAE,KAAK,EAAE,QAAQ,EAAE,YAAY,EAAE;YAC1C,MAAM,KAAK,GAAG,YAAY,IAAI,IAAI,CAAC;YACnC,MAAM,GAAG,GAAG,QAAQ,IAAI,oCAAoC,CAAC;YAE7D,OAAO;;;EAGX,KAAK;;;EAGL,GAAG;;;;;yBAKoB,KAAK;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;qHA0DuF,CAAC;QAClH,CAAC;KACF,CAAC,CAAC;AACL,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"launch-checklist.d.ts","sourceRoot":"","sources":["../../src/prompts/launch-checklist.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,SAAS,CAAC;AAEvC,wBAAgB,6BAA6B,CAAC,MAAM,EAAE,OAAO,QAyE5D"}
|
|
@@ -0,0 +1,74 @@
|
|
|
1
|
+
export function registerLaunchChecklistPrompt(server) {
|
|
2
|
+
server.addPrompt({
|
|
3
|
+
name: "launch_checklist",
|
|
4
|
+
description: "Pre-launch validation checklist. Guides an AI agent through verifying a survey is ready to launch, estimating costs, and confirming with the user before charging.",
|
|
5
|
+
arguments: [
|
|
6
|
+
{
|
|
7
|
+
name: "surveyId",
|
|
8
|
+
description: "The UUID of the survey to validate for launch",
|
|
9
|
+
required: true,
|
|
10
|
+
},
|
|
11
|
+
],
|
|
12
|
+
async load({ surveyId }) {
|
|
13
|
+
return `You are preparing to launch survey \`${surveyId}\` on the Chorus Research platform. Follow this checklist carefully:
|
|
14
|
+
|
|
15
|
+
## Pre-Launch Checklist
|
|
16
|
+
|
|
17
|
+
### 1. Retrieve & Review Survey
|
|
18
|
+
- Use \`get_survey\` to fetch the full survey definition
|
|
19
|
+
- Verify the survey is in **draft** status
|
|
20
|
+
- Check that it has a descriptive name
|
|
21
|
+
- Review all questions for clarity and completeness
|
|
22
|
+
|
|
23
|
+
### 2. Validate Survey Quality
|
|
24
|
+
- [ ] All questions have clear, unbiased wording
|
|
25
|
+
- [ ] Required questions are marked \`isRequired: true\`
|
|
26
|
+
- [ ] Conditional logic (\`visibleIf\`) is correct
|
|
27
|
+
- [ ] No duplicate question names
|
|
28
|
+
- [ ] Reasonable number of pages/questions
|
|
29
|
+
- [ ] Estimated completion time is reasonable (aim for <15 minutes)
|
|
30
|
+
- [ ] Surveys are 10 questions or less
|
|
31
|
+
|
|
32
|
+
### 3. Choose Audience
|
|
33
|
+
- Use \`list_audiences\` to see available segments
|
|
34
|
+
- Select the most appropriate audience for the research objective
|
|
35
|
+
- Note the audience's \`minTargetCompletes\` and \`maxTargetCompletes\`
|
|
36
|
+
|
|
37
|
+
### 4. Estimate Cost
|
|
38
|
+
- Use \`estimate_cost\` with the chosen audience and target completes
|
|
39
|
+
- Review the cost breakdown:
|
|
40
|
+
- Base cost per complete ($1.00 for General Population)
|
|
41
|
+
- Total cost (baseCostPerComplete × targetCompletes)
|
|
42
|
+
- If cost seems high, consider reducing target completes
|
|
43
|
+
|
|
44
|
+
### 5. Present Summary to User
|
|
45
|
+
Show the user:
|
|
46
|
+
- Survey name and question count
|
|
47
|
+
- Target audience
|
|
48
|
+
- Target completes
|
|
49
|
+
- **Total estimated cost (prominently displayed)**
|
|
50
|
+
- Estimated fielding time
|
|
51
|
+
|
|
52
|
+
### 6. Get Explicit Confirmation
|
|
53
|
+
**CRITICAL**: You MUST get explicit user confirmation before proceeding.
|
|
54
|
+
Say something like: "This will charge approximately $X to your account. Shall I proceed with the launch?"
|
|
55
|
+
|
|
56
|
+
### 7. Execute Launch (Two-Step)
|
|
57
|
+
Only after user confirms:
|
|
58
|
+
1. Call \`launch_survey\` with \`surveyId\`, \`audienceId\`, and \`targetCompletes\` → get estimate + \`confirmToken\`
|
|
59
|
+
2. Call \`launch_survey\` again with \`surveyId\` and \`confirmToken\` → execute launch
|
|
60
|
+
|
|
61
|
+
### 8. Verify Launch
|
|
62
|
+
- Confirm the launch response shows \`success: true\`
|
|
63
|
+
- Note the \`workflowId\` for status tracking
|
|
64
|
+
- Use \`get_survey_status\` to verify the survey is now **live**
|
|
65
|
+
|
|
66
|
+
## Important Reminders
|
|
67
|
+
- The confirmToken expires in **5 minutes** — don't delay between steps
|
|
68
|
+
- Launch tokens are single-use (replay attack prevention)
|
|
69
|
+
- Once launched, the survey CANNOT be edited
|
|
70
|
+
- Charges are processed immediately upon confirmation`;
|
|
71
|
+
},
|
|
72
|
+
});
|
|
73
|
+
}
|
|
74
|
+
//# sourceMappingURL=launch-checklist.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"launch-checklist.js","sourceRoot":"","sources":["../../src/prompts/launch-checklist.ts"],"names":[],"mappings":"AAEA,MAAM,UAAU,6BAA6B,CAAC,MAAe;IAC3D,MAAM,CAAC,SAAS,CAAC;QACf,IAAI,EAAE,kBAAkB;QACxB,WAAW,EACT,oKAAoK;QACtK,SAAS,EAAE;YACT;gBACE,IAAI,EAAE,UAAU;gBAChB,WAAW,EAAE,+CAA+C;gBAC5D,QAAQ,EAAE,IAAI;aACf;SACF;QACD,KAAK,CAAC,IAAI,CAAC,EAAE,QAAQ,EAAE;YACrB,OAAO,wCAAwC,QAAQ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;sDAyDP,CAAC;QACnD,CAAC;KACF,CAAC,CAAC;AACL,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"audiences.d.ts","sourceRoot":"","sources":["../../src/resources/audiences.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,SAAS,CAAC;AACvC,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,cAAc,CAAC;AAEpD,wBAAgB,yBAAyB,CACvC,MAAM,EAAE,OAAO,EACf,GAAG,EAAE,eAAe,QAarB"}
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
export function registerAudienceResources(server, api) {
|
|
2
|
+
server.addResource({
|
|
3
|
+
uri: "chorus://audiences",
|
|
4
|
+
name: "Audience Catalog",
|
|
5
|
+
description: "Full catalog of available audience segments with targeting criteria, costs, and estimated fielding times.",
|
|
6
|
+
mimeType: "application/json",
|
|
7
|
+
async load() {
|
|
8
|
+
const result = await api.listAudiences();
|
|
9
|
+
return { text: JSON.stringify(result, null, 2) };
|
|
10
|
+
},
|
|
11
|
+
});
|
|
12
|
+
}
|
|
13
|
+
//# sourceMappingURL=audiences.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"audiences.js","sourceRoot":"","sources":["../../src/resources/audiences.ts"],"names":[],"mappings":"AAGA,MAAM,UAAU,yBAAyB,CACvC,MAAe,EACf,GAAoB;IAEpB,MAAM,CAAC,WAAW,CAAC;QACjB,GAAG,EAAE,oBAAoB;QACzB,IAAI,EAAE,kBAAkB;QACxB,WAAW,EACT,2GAA2G;QAC7G,QAAQ,EAAE,kBAAkB;QAC5B,KAAK,CAAC,IAAI;YACR,MAAM,MAAM,GAAG,MAAM,GAAG,CAAC,aAAa,EAAE,CAAC;YACzC,OAAO,EAAE,IAAI,EAAE,IAAI,CAAC,SAAS,CAAC,MAAM,EAAE,IAAI,EAAE,CAAC,CAAC,EAAE,CAAC;QACnD,CAAC;KACF,CAAC,CAAC;AACL,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"pricing.d.ts","sourceRoot":"","sources":["../../src/resources/pricing.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,SAAS,CAAC;AACvC,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,cAAc,CAAC;AAEpD,wBAAgB,wBAAwB,CACtC,MAAM,EAAE,OAAO,EACf,GAAG,EAAE,eAAe,QAarB"}
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
export function registerPricingResources(server, api) {
|
|
2
|
+
server.addResource({
|
|
3
|
+
uri: "chorus://pricing/config",
|
|
4
|
+
name: "Pricing Configuration",
|
|
5
|
+
description: "Current pricing configuration including cost per response and currency.",
|
|
6
|
+
mimeType: "application/json",
|
|
7
|
+
async load() {
|
|
8
|
+
const config = await api.getPricingConfig();
|
|
9
|
+
return { text: JSON.stringify(config, null, 2) };
|
|
10
|
+
},
|
|
11
|
+
});
|
|
12
|
+
}
|
|
13
|
+
//# sourceMappingURL=pricing.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"pricing.js","sourceRoot":"","sources":["../../src/resources/pricing.ts"],"names":[],"mappings":"AAGA,MAAM,UAAU,wBAAwB,CACtC,MAAe,EACf,GAAoB;IAEpB,MAAM,CAAC,WAAW,CAAC;QACjB,GAAG,EAAE,yBAAyB;QAC9B,IAAI,EAAE,uBAAuB;QAC7B,WAAW,EACT,yEAAyE;QAC3E,QAAQ,EAAE,kBAAkB;QAC5B,KAAK,CAAC,IAAI;YACR,MAAM,MAAM,GAAG,MAAM,GAAG,CAAC,gBAAgB,EAAE,CAAC;YAC5C,OAAO,EAAE,IAAI,EAAE,IAAI,CAAC,SAAS,CAAC,MAAM,EAAE,IAAI,EAAE,CAAC,CAAC,EAAE,CAAC;QACnD,CAAC;KACF,CAAC,CAAC;AACL,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"audiences.d.ts","sourceRoot":"","sources":["../../src/tools/audiences.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,SAAS,CAAC;AAEvC,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,cAAc,CAAC;AAEpD,wBAAgB,qBAAqB,CAAC,MAAM,EAAE,OAAO,EAAE,GAAG,EAAE,eAAe,QA2B1E"}
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
import { z } from "zod";
|
|
2
|
+
export function registerAudienceTools(server, api) {
|
|
3
|
+
server.addTool({
|
|
4
|
+
name: "list_audiences",
|
|
5
|
+
description: "List all available audience segments for survey targeting. Each audience includes cost per response, targeting criteria, and estimated fielding times.",
|
|
6
|
+
annotations: { readOnlyHint: true, destructiveHint: false },
|
|
7
|
+
execute: async () => {
|
|
8
|
+
const result = await api.listAudiences();
|
|
9
|
+
return JSON.stringify(result, null, 2);
|
|
10
|
+
},
|
|
11
|
+
});
|
|
12
|
+
server.addTool({
|
|
13
|
+
name: "get_audience",
|
|
14
|
+
description: "Get detailed information about a specific audience segment including targeting criteria, cost, and fielding time estimates.",
|
|
15
|
+
annotations: { readOnlyHint: true, destructiveHint: false },
|
|
16
|
+
parameters: z.object({
|
|
17
|
+
audienceId: z
|
|
18
|
+
.string()
|
|
19
|
+
.describe('Audience identifier (e.g., "genpop")'),
|
|
20
|
+
}),
|
|
21
|
+
execute: async ({ audienceId }) => {
|
|
22
|
+
const audience = await api.getAudience(audienceId);
|
|
23
|
+
return JSON.stringify(audience, null, 2);
|
|
24
|
+
},
|
|
25
|
+
});
|
|
26
|
+
}
|
|
27
|
+
//# sourceMappingURL=audiences.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"audiences.js","sourceRoot":"","sources":["../../src/tools/audiences.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAGxB,MAAM,UAAU,qBAAqB,CAAC,MAAe,EAAE,GAAoB;IACzE,MAAM,CAAC,OAAO,CAAC;QACb,IAAI,EAAE,gBAAgB;QACtB,WAAW,EACT,wJAAwJ;QAC1J,WAAW,EAAE,EAAE,YAAY,EAAE,IAAI,EAAE,eAAe,EAAE,KAAK,EAAE;QAC3D,OAAO,EAAE,KAAK,IAAI,EAAE;YAClB,MAAM,MAAM,GAAG,MAAM,GAAG,CAAC,aAAa,EAAE,CAAC;YACzC,OAAO,IAAI,CAAC,SAAS,CAAC,MAAM,EAAE,IAAI,EAAE,CAAC,CAAC,CAAC;QACzC,CAAC;KACF,CAAC,CAAC;IAEH,MAAM,CAAC,OAAO,CAAC;QACb,IAAI,EAAE,cAAc;QACpB,WAAW,EACT,6HAA6H;QAC/H,WAAW,EAAE,EAAE,YAAY,EAAE,IAAI,EAAE,eAAe,EAAE,KAAK,EAAE;QAC3D,UAAU,EAAE,CAAC,CAAC,MAAM,CAAC;YACnB,UAAU,EAAE,CAAC;iBACV,MAAM,EAAE;iBACR,QAAQ,CAAC,sCAAsC,CAAC;SACpD,CAAC;QACF,OAAO,EAAE,KAAK,EAAE,EAAE,UAAU,EAAE,EAAE,EAAE;YAChC,MAAM,QAAQ,GAAG,MAAM,GAAG,CAAC,WAAW,CAAC,UAAU,CAAC,CAAC;YACnD,OAAO,IAAI,CAAC,SAAS,CAAC,QAAQ,EAAE,IAAI,EAAE,CAAC,CAAC,CAAC;QAC3C,CAAC;KACF,CAAC,CAAC;AACL,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"launch.d.ts","sourceRoot":"","sources":["../../src/tools/launch.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,SAAS,CAAC;AAGvC,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,cAAc,CAAC;AAEpD,wBAAgB,mBAAmB,CAAC,MAAM,EAAE,OAAO,EAAE,GAAG,EAAE,eAAe,QAwGxE"}
|
|
@@ -0,0 +1,87 @@
|
|
|
1
|
+
import { UserError } from "fastmcp";
|
|
2
|
+
import { z } from "zod";
|
|
3
|
+
export function registerLaunchTools(server, api) {
|
|
4
|
+
server.addTool({
|
|
5
|
+
name: "launch_survey",
|
|
6
|
+
description: `Launch a survey to collect responses. This is a TWO-STEP process to prevent accidental charges:
|
|
7
|
+
|
|
8
|
+
Step 1 (estimate): Call with surveyId, audienceId, and targetCompletes. Returns a cost estimate and a confirmToken (valid 5 minutes).
|
|
9
|
+
|
|
10
|
+
Step 2 (confirm): Call again with surveyId and the confirmToken from step 1 to execute the launch and charge payment.
|
|
11
|
+
|
|
12
|
+
IMPORTANT: Step 2 triggers real charges and starts a Temporal workflow for fielding. Always show the cost estimate to the user and get explicit confirmation before proceeding to step 2.`,
|
|
13
|
+
annotations: {
|
|
14
|
+
readOnlyHint: false,
|
|
15
|
+
destructiveHint: false,
|
|
16
|
+
idempotentHint: false,
|
|
17
|
+
},
|
|
18
|
+
parameters: z.object({
|
|
19
|
+
surveyId: z.string().uuid().describe("Survey ID to launch"),
|
|
20
|
+
// Step 1 params
|
|
21
|
+
audienceId: z
|
|
22
|
+
.string()
|
|
23
|
+
.optional()
|
|
24
|
+
.describe('Step 1: Audience segment ID (e.g., "genpop"). Required for estimate step.'),
|
|
25
|
+
targetCompletes: z
|
|
26
|
+
.number()
|
|
27
|
+
.int()
|
|
28
|
+
.min(0)
|
|
29
|
+
.max(5000)
|
|
30
|
+
.optional()
|
|
31
|
+
.describe("Step 1: Number of completed responses desired (0-5000, raise min for production). Required for estimate step."),
|
|
32
|
+
// Step 2 params
|
|
33
|
+
confirmToken: z
|
|
34
|
+
.string()
|
|
35
|
+
.optional()
|
|
36
|
+
.describe("Step 2: Confirmation token from the estimate step. Provide this to execute the launch."),
|
|
37
|
+
paymentMethodId: z
|
|
38
|
+
.string()
|
|
39
|
+
.optional()
|
|
40
|
+
.describe("Step 2: Optional Stripe payment method ID."),
|
|
41
|
+
}),
|
|
42
|
+
execute: async (args) => {
|
|
43
|
+
const { surveyId, audienceId, targetCompletes, confirmToken, paymentMethodId } = args;
|
|
44
|
+
// Step 2: Confirm launch
|
|
45
|
+
if (confirmToken) {
|
|
46
|
+
const result = await api.launchConfirm(surveyId, {
|
|
47
|
+
confirmToken,
|
|
48
|
+
paymentMethodId,
|
|
49
|
+
});
|
|
50
|
+
return JSON.stringify({
|
|
51
|
+
step: "confirmed",
|
|
52
|
+
message: `Survey launched successfully. Workflow ${result.workflowId} is now fielding ${result.targetCompletes} responses. Amount charged: $${result.amountCharged} ${result.currency}.`,
|
|
53
|
+
...result,
|
|
54
|
+
}, null, 2);
|
|
55
|
+
}
|
|
56
|
+
// Step 1: Get estimate
|
|
57
|
+
if (!audienceId || !targetCompletes) {
|
|
58
|
+
throw new UserError("For step 1 (estimate), both audienceId and targetCompletes are required. For step 2 (confirm), provide the confirmToken from step 1.");
|
|
59
|
+
}
|
|
60
|
+
const estimate = await api.launchEstimate(surveyId, {
|
|
61
|
+
audienceId,
|
|
62
|
+
targetCompletes,
|
|
63
|
+
});
|
|
64
|
+
return JSON.stringify({
|
|
65
|
+
step: "estimate",
|
|
66
|
+
message: `Estimated cost: $${estimate.estimatedCost} USD. The confirmToken expires at ${estimate.expiresAt}. Call launch_survey again with the confirmToken to execute the launch.`,
|
|
67
|
+
...estimate,
|
|
68
|
+
}, null, 2);
|
|
69
|
+
},
|
|
70
|
+
});
|
|
71
|
+
server.addTool({
|
|
72
|
+
name: "get_survey_status",
|
|
73
|
+
description: "Get the real-time fielding status of a survey including completion count, progress percentage, and estimated completion time. Results are cached for 30 seconds.",
|
|
74
|
+
annotations: { readOnlyHint: true, destructiveHint: false },
|
|
75
|
+
parameters: z.object({
|
|
76
|
+
surveyId: z
|
|
77
|
+
.string()
|
|
78
|
+
.uuid()
|
|
79
|
+
.describe("Survey ID to check status for"),
|
|
80
|
+
}),
|
|
81
|
+
execute: async ({ surveyId }) => {
|
|
82
|
+
const status = await api.getSurveyStatus(surveyId);
|
|
83
|
+
return JSON.stringify(status, null, 2);
|
|
84
|
+
},
|
|
85
|
+
});
|
|
86
|
+
}
|
|
87
|
+
//# sourceMappingURL=launch.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"launch.js","sourceRoot":"","sources":["../../src/tools/launch.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"pricing.d.ts","sourceRoot":"","sources":["../../src/tools/pricing.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,SAAS,CAAC;AAEvC,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,cAAc,CAAC;AAEpD,wBAAgB,oBAAoB,CAAC,MAAM,EAAE,OAAO,EAAE,GAAG,EAAE,eAAe,QAsCzE"}
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
import { z } from "zod";
|
|
2
|
+
export function registerPricingTools(server, api) {
|
|
3
|
+
server.addTool({
|
|
4
|
+
name: "estimate_cost",
|
|
5
|
+
description: "Calculate the cost to launch a survey to a specific audience. Returns cost breakdown: baseCostPerComplete × targetCompletes. Use this before launching to understand pricing.",
|
|
6
|
+
annotations: { readOnlyHint: true, destructiveHint: false },
|
|
7
|
+
parameters: z.object({
|
|
8
|
+
audienceId: z
|
|
9
|
+
.string()
|
|
10
|
+
.describe('Audience segment ID (e.g., "genpop")'),
|
|
11
|
+
targetCompletes: z
|
|
12
|
+
.number()
|
|
13
|
+
.int()
|
|
14
|
+
.min(0)
|
|
15
|
+
.max(5000)
|
|
16
|
+
.describe("Number of completed responses desired (0-5000, raise min for production)"),
|
|
17
|
+
projectId: z
|
|
18
|
+
.string()
|
|
19
|
+
.uuid()
|
|
20
|
+
.optional()
|
|
21
|
+
.describe("Optional survey project ID for LOI auto-calculation"),
|
|
22
|
+
}),
|
|
23
|
+
execute: async (args) => {
|
|
24
|
+
const estimate = await api.estimateCost(args);
|
|
25
|
+
return JSON.stringify(estimate, null, 2);
|
|
26
|
+
},
|
|
27
|
+
});
|
|
28
|
+
server.addTool({
|
|
29
|
+
name: "get_pricing_config",
|
|
30
|
+
description: "Get the current pricing configuration including cost per response and currency. Useful for understanding how costs are calculated.",
|
|
31
|
+
annotations: { readOnlyHint: true, destructiveHint: false },
|
|
32
|
+
execute: async () => {
|
|
33
|
+
const config = await api.getPricingConfig();
|
|
34
|
+
return JSON.stringify(config, null, 2);
|
|
35
|
+
},
|
|
36
|
+
});
|
|
37
|
+
}
|
|
38
|
+
//# sourceMappingURL=pricing.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"pricing.js","sourceRoot":"","sources":["../../src/tools/pricing.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAGxB,MAAM,UAAU,oBAAoB,CAAC,MAAe,EAAE,GAAoB;IACxE,MAAM,CAAC,OAAO,CAAC;QACb,IAAI,EAAE,eAAe;QACrB,WAAW,EACT,+KAA+K;QACjL,WAAW,EAAE,EAAE,YAAY,EAAE,IAAI,EAAE,eAAe,EAAE,KAAK,EAAE;QAC3D,UAAU,EAAE,CAAC,CAAC,MAAM,CAAC;YACnB,UAAU,EAAE,CAAC;iBACV,MAAM,EAAE;iBACR,QAAQ,CAAC,sCAAsC,CAAC;YACnD,eAAe,EAAE,CAAC;iBACf,MAAM,EAAE;iBACR,GAAG,EAAE;iBACL,GAAG,CAAC,CAAC,CAAC;iBACN,GAAG,CAAC,IAAI,CAAC;iBACT,QAAQ,CAAC,0EAA0E,CAAC;YACvF,SAAS,EAAE,CAAC;iBACT,MAAM,EAAE;iBACR,IAAI,EAAE;iBACN,QAAQ,EAAE;iBACV,QAAQ,CAAC,qDAAqD,CAAC;SACnE,CAAC;QACF,OAAO,EAAE,KAAK,EAAE,IAAI,EAAE,EAAE;YACtB,MAAM,QAAQ,GAAG,MAAM,GAAG,CAAC,YAAY,CAAC,IAAI,CAAC,CAAC;YAC9C,OAAO,IAAI,CAAC,SAAS,CAAC,QAAQ,EAAE,IAAI,EAAE,CAAC,CAAC,CAAC;QAC3C,CAAC;KACF,CAAC,CAAC;IAEH,MAAM,CAAC,OAAO,CAAC;QACb,IAAI,EAAE,oBAAoB;QAC1B,WAAW,EACT,oIAAoI;QACtI,WAAW,EAAE,EAAE,YAAY,EAAE,IAAI,EAAE,eAAe,EAAE,KAAK,EAAE;QAC3D,OAAO,EAAE,KAAK,IAAI,EAAE;YAClB,MAAM,MAAM,GAAG,MAAM,GAAG,CAAC,gBAAgB,EAAE,CAAC;YAC5C,OAAO,IAAI,CAAC,SAAS,CAAC,MAAM,EAAE,IAAI,EAAE,CAAC,CAAC,CAAC;QACzC,CAAC;KACF,CAAC,CAAC;AACL,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"responses.d.ts","sourceRoot":"","sources":["../../src/tools/responses.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,SAAS,CAAC;AAEvC,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,cAAc,CAAC;AAEpD,wBAAgB,qBAAqB,CAAC,MAAM,EAAE,OAAO,EAAE,GAAG,EAAE,eAAe,QAwC1E"}
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
import { z } from "zod";
|
|
2
|
+
export function registerResponseTools(server, api) {
|
|
3
|
+
server.addTool({
|
|
4
|
+
name: "get_responses",
|
|
5
|
+
description: "Export survey response data with pagination. Returns individual responses including answer data, metadata, and completion status. Only returns responses from published (launched) surveys. Default filter is 'complete' responses only. Duplicate respondents are excluded by default; set includeDuplicates=true to include them. Each response includes a supplier field indicating the panel source. Metadata includes device info (userAgent, screenSize, timezone, language), geographic data (city, state, country), and provider demographics when available.",
|
|
6
|
+
annotations: { readOnlyHint: true, destructiveHint: false },
|
|
7
|
+
parameters: z.object({
|
|
8
|
+
surveyId: z
|
|
9
|
+
.string()
|
|
10
|
+
.uuid()
|
|
11
|
+
.describe("Survey ID to export responses for"),
|
|
12
|
+
page: z
|
|
13
|
+
.number()
|
|
14
|
+
.int()
|
|
15
|
+
.positive()
|
|
16
|
+
.optional()
|
|
17
|
+
.describe("Page number (default 1)"),
|
|
18
|
+
pageSize: z
|
|
19
|
+
.number()
|
|
20
|
+
.int()
|
|
21
|
+
.min(1)
|
|
22
|
+
.max(1000)
|
|
23
|
+
.optional()
|
|
24
|
+
.describe("Results per page (default 100, max 1000)"),
|
|
25
|
+
status: z
|
|
26
|
+
.enum(["complete", "partial", "incomplete"])
|
|
27
|
+
.optional()
|
|
28
|
+
.describe("Filter by response status (default: complete)"),
|
|
29
|
+
includeDuplicates: z
|
|
30
|
+
.boolean()
|
|
31
|
+
.optional()
|
|
32
|
+
.describe("Include duplicate/flagged responses (default: false). By default, responses flagged as duplicates are excluded for clean data export."),
|
|
33
|
+
}),
|
|
34
|
+
execute: async ({ surveyId, ...params }) => {
|
|
35
|
+
const result = await api.getResponses(surveyId, params);
|
|
36
|
+
return JSON.stringify(result, null, 2);
|
|
37
|
+
},
|
|
38
|
+
});
|
|
39
|
+
}
|
|
40
|
+
//# sourceMappingURL=responses.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"responses.js","sourceRoot":"","sources":["../../src/tools/responses.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAGxB,MAAM,UAAU,qBAAqB,CAAC,MAAe,EAAE,GAAoB;IACzE,MAAM,CAAC,OAAO,CAAC;QACb,IAAI,EAAE,eAAe;QACrB,WAAW,EACT,uiBAAuiB;QACziB,WAAW,EAAE,EAAE,YAAY,EAAE,IAAI,EAAE,eAAe,EAAE,KAAK,EAAE;QAC3D,UAAU,EAAE,CAAC,CAAC,MAAM,CAAC;YACnB,QAAQ,EAAE,CAAC;iBACR,MAAM,EAAE;iBACR,IAAI,EAAE;iBACN,QAAQ,CAAC,mCAAmC,CAAC;YAChD,IAAI,EAAE,CAAC;iBACJ,MAAM,EAAE;iBACR,GAAG,EAAE;iBACL,QAAQ,EAAE;iBACV,QAAQ,EAAE;iBACV,QAAQ,CAAC,yBAAyB,CAAC;YACtC,QAAQ,EAAE,CAAC;iBACR,MAAM,EAAE;iBACR,GAAG,EAAE;iBACL,GAAG,CAAC,CAAC,CAAC;iBACN,GAAG,CAAC,IAAI,CAAC;iBACT,QAAQ,EAAE;iBACV,QAAQ,CAAC,0CAA0C,CAAC;YACvD,MAAM,EAAE,CAAC;iBACN,IAAI,CAAC,CAAC,UAAU,EAAE,SAAS,EAAE,YAAY,CAAC,CAAC;iBAC3C,QAAQ,EAAE;iBACV,QAAQ,CAAC,+CAA+C,CAAC;YAC5D,iBAAiB,EAAE,CAAC;iBACjB,OAAO,EAAE;iBACT,QAAQ,EAAE;iBACV,QAAQ,CACP,uIAAuI,CACxI;SACJ,CAAC;QACF,OAAO,EAAE,KAAK,EAAE,EAAE,QAAQ,EAAE,GAAG,MAAM,EAAE,EAAE,EAAE;YACzC,MAAM,MAAM,GAAG,MAAM,GAAG,CAAC,YAAY,CAAC,QAAQ,EAAE,MAAM,CAAC,CAAC;YACxD,OAAO,IAAI,CAAC,SAAS,CAAC,MAAM,EAAE,IAAI,EAAE,CAAC,CAAC,CAAC;QACzC,CAAC;KACF,CAAC,CAAC;AACL,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"surveys.d.ts","sourceRoot":"","sources":["../../src/tools/surveys.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,SAAS,CAAC;AAEvC,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,cAAc,CAAC;AAEpD,wBAAgB,mBAAmB,CAAC,MAAM,EAAE,OAAO,EAAE,GAAG,EAAE,eAAe,QA8ExE"}
|
|
@@ -0,0 +1,74 @@
|
|
|
1
|
+
import { z } from "zod";
|
|
2
|
+
export function registerSurveyTools(server, api) {
|
|
3
|
+
server.addTool({
|
|
4
|
+
name: "list_surveys",
|
|
5
|
+
description: "List surveys with optional filtering by status and pagination. Returns survey metadata (id, name, status, dates) but not the full JSON.",
|
|
6
|
+
annotations: { readOnlyHint: true, destructiveHint: false, openWorldHint: true },
|
|
7
|
+
parameters: z.object({
|
|
8
|
+
status: z
|
|
9
|
+
.enum(["draft", "live", "complete", "cancelled"])
|
|
10
|
+
.optional()
|
|
11
|
+
.describe("Filter by survey status"),
|
|
12
|
+
page: z.number().int().positive().optional().describe("Page number (default 1)"),
|
|
13
|
+
pageSize: z
|
|
14
|
+
.number()
|
|
15
|
+
.int()
|
|
16
|
+
.min(1)
|
|
17
|
+
.max(100)
|
|
18
|
+
.optional()
|
|
19
|
+
.describe("Results per page (default 20, max 100)"),
|
|
20
|
+
sort: z
|
|
21
|
+
.enum(["createdAt", "updatedAt", "name"])
|
|
22
|
+
.optional()
|
|
23
|
+
.describe("Sort field"),
|
|
24
|
+
order: z.enum(["asc", "desc"]).optional().describe("Sort order"),
|
|
25
|
+
}),
|
|
26
|
+
execute: async (args) => {
|
|
27
|
+
const result = await api.listSurveys(args);
|
|
28
|
+
return JSON.stringify(result, null, 2);
|
|
29
|
+
},
|
|
30
|
+
});
|
|
31
|
+
server.addTool({
|
|
32
|
+
name: "get_survey",
|
|
33
|
+
description: "Get full details of a specific survey including the complete JSON definition, status, and metadata.",
|
|
34
|
+
annotations: { readOnlyHint: true, destructiveHint: false },
|
|
35
|
+
parameters: z.object({
|
|
36
|
+
surveyId: z.string().uuid().describe("Survey ID (UUID)"),
|
|
37
|
+
}),
|
|
38
|
+
execute: async ({ surveyId }) => {
|
|
39
|
+
const survey = await api.getSurvey(surveyId);
|
|
40
|
+
return JSON.stringify(survey, null, 2);
|
|
41
|
+
},
|
|
42
|
+
});
|
|
43
|
+
server.addTool({
|
|
44
|
+
name: "create_survey",
|
|
45
|
+
description: "Create a new survey draft. Provide a name, the JSON definition, and a target number of completed responses. The survey will be created in 'draft' status.",
|
|
46
|
+
annotations: { readOnlyHint: false, destructiveHint: false },
|
|
47
|
+
parameters: z.object({
|
|
48
|
+
name: z
|
|
49
|
+
.string()
|
|
50
|
+
.min(1)
|
|
51
|
+
.max(255)
|
|
52
|
+
.describe("Survey name (1-255 characters)"),
|
|
53
|
+
survey: z
|
|
54
|
+
.record(z.unknown())
|
|
55
|
+
.describe("JSON definition. Must include `pages` array with question elements."),
|
|
56
|
+
targetCompletes: z
|
|
57
|
+
.number()
|
|
58
|
+
.int()
|
|
59
|
+
.min(0)
|
|
60
|
+
.max(5000)
|
|
61
|
+
.describe("Target number of completed responses (0-5000, raise min for production)"),
|
|
62
|
+
description: z
|
|
63
|
+
.string()
|
|
64
|
+
.max(1000)
|
|
65
|
+
.optional()
|
|
66
|
+
.describe("Optional survey description (max 1000 chars)"),
|
|
67
|
+
}),
|
|
68
|
+
execute: async (args) => {
|
|
69
|
+
const survey = await api.createSurvey(args);
|
|
70
|
+
return JSON.stringify(survey, null, 2);
|
|
71
|
+
},
|
|
72
|
+
});
|
|
73
|
+
}
|
|
74
|
+
//# sourceMappingURL=surveys.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"surveys.js","sourceRoot":"","sources":["../../src/tools/surveys.ts"],"names":[],"mappings":"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"}
|
package/package.json
ADDED
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@chorus-research/mcp",
|
|
3
|
+
"version": "0.1.0",
|
|
4
|
+
"description": "MCP server for the Chorus Research survey platform",
|
|
5
|
+
"type": "module",
|
|
6
|
+
"main": "dist/index.js",
|
|
7
|
+
"bin": {
|
|
8
|
+
"chorus-research-mcp": "dist/index.js",
|
|
9
|
+
"chorus-mcp": "dist/index.js"
|
|
10
|
+
},
|
|
11
|
+
"scripts": {
|
|
12
|
+
"build": "tsc",
|
|
13
|
+
"start": "node dist/index.js",
|
|
14
|
+
"dev": "tsx src/index.ts",
|
|
15
|
+
"inspect": "npx fastmcp inspect src/index.ts",
|
|
16
|
+
"test": "vitest run",
|
|
17
|
+
"test:watch": "vitest"
|
|
18
|
+
},
|
|
19
|
+
"dependencies": {
|
|
20
|
+
"fastmcp": "^3.34.0",
|
|
21
|
+
"zod": "^3.23.8"
|
|
22
|
+
},
|
|
23
|
+
"devDependencies": {
|
|
24
|
+
"@types/node": "^22.10.0",
|
|
25
|
+
"tsx": "^4.19.0",
|
|
26
|
+
"typescript": "^5.7.0",
|
|
27
|
+
"vitest": "^3.0.0"
|
|
28
|
+
},
|
|
29
|
+
"engines": {
|
|
30
|
+
"node": ">=20"
|
|
31
|
+
},
|
|
32
|
+
"files": [
|
|
33
|
+
"dist"
|
|
34
|
+
],
|
|
35
|
+
"keywords": [
|
|
36
|
+
"mcp",
|
|
37
|
+
"survey",
|
|
38
|
+
"research",
|
|
39
|
+
"chorus"
|
|
40
|
+
],
|
|
41
|
+
"license": "Proprietary"
|
|
42
|
+
}
|