@heisee/letsclarify-mcp 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.
- package/README.md +48 -0
- package/build/client.d.ts +61 -0
- package/build/client.d.ts.map +1 -0
- package/build/client.js +57 -0
- package/build/client.js.map +1 -0
- package/build/index.d.ts +3 -0
- package/build/index.d.ts.map +1 -0
- package/build/index.js +15 -0
- package/build/index.js.map +1 -0
- package/build/server.d.ts +4 -0
- package/build/server.d.ts.map +1 -0
- package/build/server.js +118 -0
- package/build/server.js.map +1 -0
- package/build/tools/add-recipients.d.ts +4 -0
- package/build/tools/add-recipients.d.ts.map +1 -0
- package/build/tools/add-recipients.js +21 -0
- package/build/tools/add-recipients.js.map +1 -0
- package/build/tools/create-form.d.ts +4 -0
- package/build/tools/create-form.d.ts.map +1 -0
- package/build/tools/create-form.js +79 -0
- package/build/tools/create-form.js.map +1 -0
- package/build/tools/delete-form.d.ts +4 -0
- package/build/tools/delete-form.d.ts.map +1 -0
- package/build/tools/delete-form.js +21 -0
- package/build/tools/delete-form.js.map +1 -0
- package/build/tools/get-form-results.d.ts +4 -0
- package/build/tools/get-form-results.d.ts.map +1 -0
- package/build/tools/get-form-results.js +32 -0
- package/build/tools/get-form-results.js.map +1 -0
- package/build/tools/get-form-summary.d.ts +4 -0
- package/build/tools/get-form-summary.d.ts.map +1 -0
- package/build/tools/get-form-summary.js +20 -0
- package/build/tools/get-form-summary.js.map +1 -0
- package/package.json +43 -0
package/README.md
ADDED
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
# @heisee/letsclarify-mcp
|
|
2
|
+
|
|
3
|
+
MCP server for [LetsClarify](https://letsclarify.ai) — Human-in-the-Loop API for AI agents.
|
|
4
|
+
|
|
5
|
+
Create structured forms via API, share URLs with humans, get JSON back.
|
|
6
|
+
|
|
7
|
+
## Setup
|
|
8
|
+
|
|
9
|
+
```json
|
|
10
|
+
{
|
|
11
|
+
"mcpServers": {
|
|
12
|
+
"letsclarify": {
|
|
13
|
+
"command": "npx",
|
|
14
|
+
"args": ["-y", "@heisee/letsclarify-mcp"],
|
|
15
|
+
"env": {
|
|
16
|
+
"LETSCLARIFY_API_KEY": "lc_your_key_here"
|
|
17
|
+
}
|
|
18
|
+
}
|
|
19
|
+
}
|
|
20
|
+
}
|
|
21
|
+
```
|
|
22
|
+
|
|
23
|
+
## Tools
|
|
24
|
+
|
|
25
|
+
| Tool | Description |
|
|
26
|
+
|------|-------------|
|
|
27
|
+
| `create_form` | Create a form with schema, title, context, recipients |
|
|
28
|
+
| `get_form_summary` | Quick overview: submitted/pending counts |
|
|
29
|
+
| `get_form_results` | Paginated results with filters and file support |
|
|
30
|
+
| `delete_form` | Permanently delete a form and all its data |
|
|
31
|
+
| `add_recipients` | Add more recipient slots to an existing form |
|
|
32
|
+
|
|
33
|
+
## Resources
|
|
34
|
+
|
|
35
|
+
| URI | Description |
|
|
36
|
+
|-----|-------------|
|
|
37
|
+
| `letsclarify://schema-dsl` | Schema DSL reference (field types, validation, file config) |
|
|
38
|
+
|
|
39
|
+
## Environment Variables
|
|
40
|
+
|
|
41
|
+
| Variable | Required | Description |
|
|
42
|
+
|----------|----------|-------------|
|
|
43
|
+
| `LETSCLARIFY_API_KEY` | Yes | API key (starts with `lc_`) |
|
|
44
|
+
| `LETSCLARIFY_BASE_URL` | No | Override base URL (default: `https://letsclarify.ai`) |
|
|
45
|
+
|
|
46
|
+
## License
|
|
47
|
+
|
|
48
|
+
MIT
|
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
export interface ApiError {
|
|
2
|
+
error: string;
|
|
3
|
+
message?: string;
|
|
4
|
+
messages?: string[];
|
|
5
|
+
}
|
|
6
|
+
export declare class LetsClarifyClient {
|
|
7
|
+
private baseUrl;
|
|
8
|
+
private apiKey;
|
|
9
|
+
constructor(apiKey: string, baseUrl?: string);
|
|
10
|
+
private request;
|
|
11
|
+
createForm(body: {
|
|
12
|
+
schema: unknown[];
|
|
13
|
+
title?: string;
|
|
14
|
+
context_markdown?: string;
|
|
15
|
+
recipient_count?: number;
|
|
16
|
+
retention_days?: number;
|
|
17
|
+
webhook_url?: string;
|
|
18
|
+
theme_color?: string;
|
|
19
|
+
}): Promise<{
|
|
20
|
+
form_token: string;
|
|
21
|
+
delete_token: string;
|
|
22
|
+
base_url_template: string;
|
|
23
|
+
poll_url: string;
|
|
24
|
+
summary_url: string;
|
|
25
|
+
delete_url: string;
|
|
26
|
+
recipients: string[];
|
|
27
|
+
}>;
|
|
28
|
+
getFormSummary(formToken: string): Promise<{
|
|
29
|
+
expired: boolean;
|
|
30
|
+
known_total: number;
|
|
31
|
+
submitted_total: number;
|
|
32
|
+
pending_total: number;
|
|
33
|
+
updated_at_max: string;
|
|
34
|
+
}>;
|
|
35
|
+
getFormResults(formToken: string, params?: {
|
|
36
|
+
limit?: string;
|
|
37
|
+
cursor?: string;
|
|
38
|
+
status?: string;
|
|
39
|
+
updated_since?: string;
|
|
40
|
+
include_files?: string;
|
|
41
|
+
}): Promise<{
|
|
42
|
+
expired: boolean;
|
|
43
|
+
next_cursor: string | null;
|
|
44
|
+
server_time: string;
|
|
45
|
+
results: Array<{
|
|
46
|
+
recipient_uuid: string;
|
|
47
|
+
status: string;
|
|
48
|
+
submitted_at: string | null;
|
|
49
|
+
updated_at: string;
|
|
50
|
+
response_json: Record<string, unknown> | null;
|
|
51
|
+
files?: unknown;
|
|
52
|
+
}>;
|
|
53
|
+
}>;
|
|
54
|
+
deleteForm(formToken: string, deleteToken: string): Promise<{
|
|
55
|
+
deleted: boolean;
|
|
56
|
+
}>;
|
|
57
|
+
addRecipients(formToken: string, count?: number): Promise<{
|
|
58
|
+
recipients: string[];
|
|
59
|
+
}>;
|
|
60
|
+
}
|
|
61
|
+
//# sourceMappingURL=client.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"client.d.ts","sourceRoot":"","sources":["../src/client.ts"],"names":[],"mappings":"AAAA,MAAM,WAAW,QAAQ;IACvB,KAAK,EAAE,MAAM,CAAC;IACd,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,QAAQ,CAAC,EAAE,MAAM,EAAE,CAAC;CACrB;AAED,qBAAa,iBAAiB;IAC5B,OAAO,CAAC,OAAO,CAAS;IACxB,OAAO,CAAC,MAAM,CAAS;gBAEX,MAAM,EAAE,MAAM,EAAE,OAAO,SAA2B;YAKhD,OAAO;IAiDf,UAAU,CAAC,IAAI,EAAE;QACrB,MAAM,EAAE,OAAO,EAAE,CAAC;QAClB,KAAK,CAAC,EAAE,MAAM,CAAC;QACf,gBAAgB,CAAC,EAAE,MAAM,CAAC;QAC1B,eAAe,CAAC,EAAE,MAAM,CAAC;QACzB,cAAc,CAAC,EAAE,MAAM,CAAC;QACxB,WAAW,CAAC,EAAE,MAAM,CAAC;QACrB,WAAW,CAAC,EAAE,MAAM,CAAC;KACtB;oBAEe,MAAM;sBACJ,MAAM;2BACD,MAAM;kBACf,MAAM;qBACH,MAAM;oBACP,MAAM;oBACN,MAAM,EAAE;;IAIlB,cAAc,CAAC,SAAS,EAAE,MAAM;iBAEzB,OAAO;qBACH,MAAM;yBACF,MAAM;uBACR,MAAM;wBACL,MAAM;;IAIpB,cAAc,CAClB,SAAS,EAAE,MAAM,EACjB,MAAM,CAAC,EAAE;QACP,KAAK,CAAC,EAAE,MAAM,CAAC;QACf,MAAM,CAAC,EAAE,MAAM,CAAC;QAChB,MAAM,CAAC,EAAE,MAAM,CAAC;QAChB,aAAa,CAAC,EAAE,MAAM,CAAC;QACvB,aAAa,CAAC,EAAE,MAAM,CAAC;KACxB;iBAGU,OAAO;qBACH,MAAM,GAAG,IAAI;qBACb,MAAM;iBACV,KAAK,CAAC;YACb,cAAc,EAAE,MAAM,CAAC;YACvB,MAAM,EAAE,MAAM,CAAC;YACf,YAAY,EAAE,MAAM,GAAG,IAAI,CAAC;YAC5B,UAAU,EAAE,MAAM,CAAC;YACnB,aAAa,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,IAAI,CAAC;YAC9C,KAAK,CAAC,EAAE,OAAO,CAAC;SACjB,CAAC;;IAIA,UAAU,CAAC,SAAS,EAAE,MAAM,EAAE,WAAW,EAAE,MAAM;iBACtB,OAAO;;IAOlC,aAAa,CAAC,SAAS,EAAE,MAAM,EAAE,KAAK,CAAC,EAAE,MAAM;oBACjB,MAAM,EAAE;;CAM7C"}
|
package/build/client.js
ADDED
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
export class LetsClarifyClient {
|
|
2
|
+
baseUrl;
|
|
3
|
+
apiKey;
|
|
4
|
+
constructor(apiKey, baseUrl = "https://letsclarify.ai") {
|
|
5
|
+
this.apiKey = apiKey;
|
|
6
|
+
this.baseUrl = baseUrl.replace(/\/+$/, "");
|
|
7
|
+
}
|
|
8
|
+
async request(method, path, options = {}) {
|
|
9
|
+
const url = new URL(`${this.baseUrl}${path}`);
|
|
10
|
+
if (options.params) {
|
|
11
|
+
for (const [key, value] of Object.entries(options.params)) {
|
|
12
|
+
if (value !== undefined) {
|
|
13
|
+
url.searchParams.set(key, value);
|
|
14
|
+
}
|
|
15
|
+
}
|
|
16
|
+
}
|
|
17
|
+
const headers = {
|
|
18
|
+
Authorization: `Bearer ${this.apiKey}`,
|
|
19
|
+
Accept: "application/json",
|
|
20
|
+
...options.headers,
|
|
21
|
+
};
|
|
22
|
+
if (options.body) {
|
|
23
|
+
headers["Content-Type"] = "application/json";
|
|
24
|
+
}
|
|
25
|
+
const response = await fetch(url.toString(), {
|
|
26
|
+
method,
|
|
27
|
+
headers,
|
|
28
|
+
body: options.body ? JSON.stringify(options.body) : undefined,
|
|
29
|
+
});
|
|
30
|
+
const json = await response.json();
|
|
31
|
+
if (!response.ok) {
|
|
32
|
+
const err = json;
|
|
33
|
+
const detail = err.messages
|
|
34
|
+
? err.messages.join("; ")
|
|
35
|
+
: err.message || err.error;
|
|
36
|
+
throw new Error(`API ${response.status}: ${detail}`);
|
|
37
|
+
}
|
|
38
|
+
return json;
|
|
39
|
+
}
|
|
40
|
+
// --- Public methods ---
|
|
41
|
+
async createForm(body) {
|
|
42
|
+
return this.request("POST", "/api/v1/forms", { body });
|
|
43
|
+
}
|
|
44
|
+
async getFormSummary(formToken) {
|
|
45
|
+
return this.request("GET", `/api/v1/forms/${formToken}/summary`);
|
|
46
|
+
}
|
|
47
|
+
async getFormResults(formToken, params) {
|
|
48
|
+
return this.request("GET", `/api/v1/forms/${formToken}/results`, { params });
|
|
49
|
+
}
|
|
50
|
+
async deleteForm(formToken, deleteToken) {
|
|
51
|
+
return this.request("DELETE", `/api/v1/forms/${formToken}`, { headers: { "X-Delete-Token": deleteToken } });
|
|
52
|
+
}
|
|
53
|
+
async addRecipients(formToken, count) {
|
|
54
|
+
return this.request("POST", `/api/v1/forms/${formToken}/recipients`, { body: count !== undefined ? { count } : {} });
|
|
55
|
+
}
|
|
56
|
+
}
|
|
57
|
+
//# 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/build/index.d.ts
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":""}
|
package/build/index.js
ADDED
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js";
|
|
3
|
+
import { LetsClarifyClient } from "./client.js";
|
|
4
|
+
import { createServer } from "./server.js";
|
|
5
|
+
const apiKey = process.env.LETSCLARIFY_API_KEY;
|
|
6
|
+
if (!apiKey) {
|
|
7
|
+
console.error("Error: LETSCLARIFY_API_KEY environment variable is required.");
|
|
8
|
+
process.exit(1);
|
|
9
|
+
}
|
|
10
|
+
const baseUrl = process.env.LETSCLARIFY_BASE_URL || "https://letsclarify.ai";
|
|
11
|
+
const client = new LetsClarifyClient(apiKey, baseUrl);
|
|
12
|
+
const server = createServer(client);
|
|
13
|
+
const transport = new StdioServerTransport();
|
|
14
|
+
await server.connect(transport);
|
|
15
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":";AAEA,OAAO,EAAE,oBAAoB,EAAE,MAAM,2CAA2C,CAAC;AACjF,OAAO,EAAE,iBAAiB,EAAE,MAAM,aAAa,CAAC;AAChD,OAAO,EAAE,YAAY,EAAE,MAAM,aAAa,CAAC;AAE3C,MAAM,MAAM,GAAG,OAAO,CAAC,GAAG,CAAC,mBAAmB,CAAC;AAC/C,IAAI,CAAC,MAAM,EAAE,CAAC;IACZ,OAAO,CAAC,KAAK,CAAC,8DAA8D,CAAC,CAAC;IAC9E,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;AAClB,CAAC;AAED,MAAM,OAAO,GAAG,OAAO,CAAC,GAAG,CAAC,oBAAoB,IAAI,wBAAwB,CAAC;AAC7E,MAAM,MAAM,GAAG,IAAI,iBAAiB,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;AACtD,MAAM,MAAM,GAAG,YAAY,CAAC,MAAM,CAAC,CAAC;AAEpC,MAAM,SAAS,GAAG,IAAI,oBAAoB,EAAE,CAAC;AAC7C,MAAM,MAAM,CAAC,OAAO,CAAC,SAAS,CAAC,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"server.d.ts","sourceRoot":"","sources":["../src/server.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,MAAM,yCAAyC,CAAC;AACpE,OAAO,EAAE,iBAAiB,EAAE,MAAM,aAAa,CAAC;AA6FhD,wBAAgB,YAAY,CAAC,MAAM,EAAE,iBAAiB,GAAG,SAAS,CA6BjE"}
|
package/build/server.js
ADDED
|
@@ -0,0 +1,118 @@
|
|
|
1
|
+
import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
|
|
2
|
+
import { registerCreateForm } from "./tools/create-form.js";
|
|
3
|
+
import { registerGetFormSummary } from "./tools/get-form-summary.js";
|
|
4
|
+
import { registerGetFormResults } from "./tools/get-form-results.js";
|
|
5
|
+
import { registerDeleteForm } from "./tools/delete-form.js";
|
|
6
|
+
import { registerAddRecipients } from "./tools/add-recipients.js";
|
|
7
|
+
const SCHEMA_DSL_RESOURCE = `# LetsClarify Schema DSL Reference
|
|
8
|
+
|
|
9
|
+
## Field Types
|
|
10
|
+
|
|
11
|
+
| Type | Description | Requires \`options\` |
|
|
12
|
+
|---|---|---|
|
|
13
|
+
| \`text\` | Single-line text input | No |
|
|
14
|
+
| \`textarea\` | Multi-line text input | No |
|
|
15
|
+
| \`checkbox\` | Single boolean checkbox | No |
|
|
16
|
+
| \`checkbox_group\` | Multiple checkboxes | Yes |
|
|
17
|
+
| \`radio\` | Radio button group | Yes |
|
|
18
|
+
| \`select\` | Dropdown select | Yes |
|
|
19
|
+
| \`file\` | File upload | No |
|
|
20
|
+
|
|
21
|
+
## Field Object Structure
|
|
22
|
+
|
|
23
|
+
\`\`\`json
|
|
24
|
+
{
|
|
25
|
+
"id": "field_name", // unique, letters/digits/underscores
|
|
26
|
+
"type": "text", // one of the types above
|
|
27
|
+
"label": "Your Name", // human-readable label
|
|
28
|
+
"required": true, // optional, default false
|
|
29
|
+
"placeholder": "Enter…", // optional
|
|
30
|
+
"description": "Help text" // optional
|
|
31
|
+
}
|
|
32
|
+
\`\`\`
|
|
33
|
+
|
|
34
|
+
## Options (required for radio, select, checkbox_group)
|
|
35
|
+
|
|
36
|
+
\`\`\`json
|
|
37
|
+
"options": [
|
|
38
|
+
{ "value": "yes", "label": "Yes" },
|
|
39
|
+
{ "value": "no", "label": "No" }
|
|
40
|
+
]
|
|
41
|
+
\`\`\`
|
|
42
|
+
|
|
43
|
+
## Validation Rules (optional)
|
|
44
|
+
|
|
45
|
+
- \`min_length\` / \`max_length\` — for text/textarea
|
|
46
|
+
- \`pattern\` — regex string for text/textarea
|
|
47
|
+
- \`min_items\` / \`max_items\` — for checkbox_group
|
|
48
|
+
|
|
49
|
+
\`\`\`json
|
|
50
|
+
"validation": { "min_length": 10, "max_length": 500 }
|
|
51
|
+
\`\`\`
|
|
52
|
+
|
|
53
|
+
## File Config (optional, for file type only)
|
|
54
|
+
|
|
55
|
+
- \`accept\` — array of MIME types or extensions: \`["image/*", ".pdf"]\`
|
|
56
|
+
- \`max_size_mb\` — max file size in MB (1–10)
|
|
57
|
+
- \`max_files\` — max number of files (1–10)
|
|
58
|
+
|
|
59
|
+
\`\`\`json
|
|
60
|
+
"file": { "accept": [".pdf", "image/*"], "max_size_mb": 5, "max_files": 3 }
|
|
61
|
+
\`\`\`
|
|
62
|
+
|
|
63
|
+
## Example Schema
|
|
64
|
+
|
|
65
|
+
\`\`\`json
|
|
66
|
+
[
|
|
67
|
+
{
|
|
68
|
+
"id": "decision",
|
|
69
|
+
"type": "radio",
|
|
70
|
+
"label": "Your decision",
|
|
71
|
+
"required": true,
|
|
72
|
+
"options": [
|
|
73
|
+
{ "value": "approve", "label": "Approve" },
|
|
74
|
+
{ "value": "reject", "label": "Reject" }
|
|
75
|
+
]
|
|
76
|
+
},
|
|
77
|
+
{
|
|
78
|
+
"id": "notes",
|
|
79
|
+
"type": "textarea",
|
|
80
|
+
"label": "Additional notes",
|
|
81
|
+
"validation": { "max_length": 1000 }
|
|
82
|
+
},
|
|
83
|
+
{
|
|
84
|
+
"id": "attachment",
|
|
85
|
+
"type": "file",
|
|
86
|
+
"label": "Supporting document",
|
|
87
|
+
"file": { "accept": [".pdf", ".docx"], "max_size_mb": 10 }
|
|
88
|
+
}
|
|
89
|
+
]
|
|
90
|
+
\`\`\`
|
|
91
|
+
`;
|
|
92
|
+
export function createServer(client) {
|
|
93
|
+
const server = new McpServer({
|
|
94
|
+
name: "letsclarify",
|
|
95
|
+
version: "1.0.0",
|
|
96
|
+
});
|
|
97
|
+
// Register tools
|
|
98
|
+
registerCreateForm(server, client);
|
|
99
|
+
registerGetFormSummary(server, client);
|
|
100
|
+
registerGetFormResults(server, client);
|
|
101
|
+
registerDeleteForm(server, client);
|
|
102
|
+
registerAddRecipients(server, client);
|
|
103
|
+
// Register schema DSL resource
|
|
104
|
+
server.resource("schema-dsl", "letsclarify://schema-dsl", {
|
|
105
|
+
description: "Schema DSL reference for LetsClarify form fields — types, validation, file config, and examples.",
|
|
106
|
+
mimeType: "text/markdown",
|
|
107
|
+
}, async () => ({
|
|
108
|
+
contents: [
|
|
109
|
+
{
|
|
110
|
+
uri: "letsclarify://schema-dsl",
|
|
111
|
+
mimeType: "text/markdown",
|
|
112
|
+
text: SCHEMA_DSL_RESOURCE,
|
|
113
|
+
},
|
|
114
|
+
],
|
|
115
|
+
}));
|
|
116
|
+
return server;
|
|
117
|
+
}
|
|
118
|
+
//# sourceMappingURL=server.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"server.js","sourceRoot":"","sources":["../src/server.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,MAAM,yCAAyC,CAAC;AAEpE,OAAO,EAAE,kBAAkB,EAAE,MAAM,wBAAwB,CAAC;AAC5D,OAAO,EAAE,sBAAsB,EAAE,MAAM,6BAA6B,CAAC;AACrE,OAAO,EAAE,sBAAsB,EAAE,MAAM,6BAA6B,CAAC;AACrE,OAAO,EAAE,kBAAkB,EAAE,MAAM,wBAAwB,CAAC;AAC5D,OAAO,EAAE,qBAAqB,EAAE,MAAM,2BAA2B,CAAC;AAElE,MAAM,mBAAmB,GAAG;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CAoF3B,CAAC;AAEF,MAAM,UAAU,YAAY,CAAC,MAAyB;IACpD,MAAM,MAAM,GAAG,IAAI,SAAS,CAAC;QAC3B,IAAI,EAAE,aAAa;QACnB,OAAO,EAAE,OAAO;KACjB,CAAC,CAAC;IAEH,iBAAiB;IACjB,kBAAkB,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IACnC,sBAAsB,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IACvC,sBAAsB,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IACvC,kBAAkB,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IACnC,qBAAqB,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IAEtC,+BAA+B;IAC/B,MAAM,CAAC,QAAQ,CAAC,YAAY,EAAE,0BAA0B,EAAE;QACxD,WAAW,EACT,kGAAkG;QACpG,QAAQ,EAAE,eAAe;KAC1B,EAAE,KAAK,IAAI,EAAE,CAAC,CAAC;QACd,QAAQ,EAAE;YACR;gBACE,GAAG,EAAE,0BAA0B;gBAC/B,QAAQ,EAAE,eAAe;gBACzB,IAAI,EAAE,mBAAmB;aAC1B;SACF;KACF,CAAC,CAAC,CAAC;IAEJ,OAAO,MAAM,CAAC;AAChB,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"add-recipients.d.ts","sourceRoot":"","sources":["../../src/tools/add-recipients.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,MAAM,yCAAyC,CAAC;AAEpE,OAAO,EAAE,iBAAiB,EAAE,MAAM,cAAc,CAAC;AAEjD,wBAAgB,qBAAqB,CAAC,MAAM,EAAE,SAAS,EAAE,MAAM,EAAE,iBAAiB,QAsBjF"}
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import { z } from "zod";
|
|
2
|
+
export function registerAddRecipients(server, client) {
|
|
3
|
+
server.tool("add_recipients", "Add more recipient slots to an existing form. Returns new UUIDs. Build URLs using the base_url_template from create_form. Cannot be used on expired forms.", {
|
|
4
|
+
form_token: z.string().describe("The form token returned by create_form"),
|
|
5
|
+
count: z.number().int().min(1).max(1000).optional().describe("Number of new recipients to add (default: 1)"),
|
|
6
|
+
}, async (args) => {
|
|
7
|
+
try {
|
|
8
|
+
const result = await client.addRecipients(args.form_token, args.count);
|
|
9
|
+
return {
|
|
10
|
+
content: [{ type: "text", text: JSON.stringify(result, null, 2) }],
|
|
11
|
+
};
|
|
12
|
+
}
|
|
13
|
+
catch (error) {
|
|
14
|
+
return {
|
|
15
|
+
content: [{ type: "text", text: `Error: ${error instanceof Error ? error.message : String(error)}` }],
|
|
16
|
+
isError: true,
|
|
17
|
+
};
|
|
18
|
+
}
|
|
19
|
+
});
|
|
20
|
+
}
|
|
21
|
+
//# sourceMappingURL=add-recipients.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"add-recipients.js","sourceRoot":"","sources":["../../src/tools/add-recipients.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAGxB,MAAM,UAAU,qBAAqB,CAAC,MAAiB,EAAE,MAAyB;IAChF,MAAM,CAAC,IAAI,CACT,gBAAgB,EAChB,4JAA4J,EAC5J;QACE,UAAU,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,CAAC,wCAAwC,CAAC;QACzE,KAAK,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,GAAG,EAAE,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC,QAAQ,EAAE,CAAC,QAAQ,CAAC,8CAA8C,CAAC;KAC7G,EACD,KAAK,EAAE,IAAI,EAAE,EAAE;QACb,IAAI,CAAC;YACH,MAAM,MAAM,GAAG,MAAM,MAAM,CAAC,aAAa,CAAC,IAAI,CAAC,UAAU,EAAE,IAAI,CAAC,KAAK,CAAC,CAAC;YACvE,OAAO;gBACL,OAAO,EAAE,CAAC,EAAE,IAAI,EAAE,MAAe,EAAE,IAAI,EAAE,IAAI,CAAC,SAAS,CAAC,MAAM,EAAE,IAAI,EAAE,CAAC,CAAC,EAAE,CAAC;aAC5E,CAAC;QACJ,CAAC;QAAC,OAAO,KAAK,EAAE,CAAC;YACf,OAAO;gBACL,OAAO,EAAE,CAAC,EAAE,IAAI,EAAE,MAAe,EAAE,IAAI,EAAE,UAAU,KAAK,YAAY,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,EAAE,EAAE,CAAC;gBAC9G,OAAO,EAAE,IAAI;aACd,CAAC;QACJ,CAAC;IACH,CAAC,CACF,CAAC;AACJ,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"create-form.d.ts","sourceRoot":"","sources":["../../src/tools/create-form.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,MAAM,yCAAyC,CAAC;AAEpE,OAAO,EAAE,iBAAiB,EAAE,MAAM,cAAc,CAAC;AAqCjD,wBAAgB,kBAAkB,CAAC,MAAM,EAAE,SAAS,EAAE,MAAM,EAAE,iBAAiB,QAyD9E"}
|
|
@@ -0,0 +1,79 @@
|
|
|
1
|
+
import { z } from "zod";
|
|
2
|
+
const FieldValidation = z
|
|
3
|
+
.object({
|
|
4
|
+
min_length: z.number().int().nonnegative().optional(),
|
|
5
|
+
max_length: z.number().int().positive().optional(),
|
|
6
|
+
pattern: z.string().optional(),
|
|
7
|
+
min_items: z.number().int().nonnegative().optional(),
|
|
8
|
+
max_items: z.number().int().positive().optional(),
|
|
9
|
+
})
|
|
10
|
+
.optional();
|
|
11
|
+
const FileConfig = z
|
|
12
|
+
.object({
|
|
13
|
+
accept: z.array(z.string()).optional(),
|
|
14
|
+
max_size_mb: z.number().min(1).max(10).optional(),
|
|
15
|
+
max_files: z.number().int().min(1).max(10).optional(),
|
|
16
|
+
})
|
|
17
|
+
.optional();
|
|
18
|
+
const Option = z.object({
|
|
19
|
+
value: z.string(),
|
|
20
|
+
label: z.string(),
|
|
21
|
+
});
|
|
22
|
+
const SchemaField = z.object({
|
|
23
|
+
id: z.string().describe("Unique field identifier (letters, digits, underscores)"),
|
|
24
|
+
type: z.enum(["text", "textarea", "checkbox", "checkbox_group", "radio", "select", "file"]),
|
|
25
|
+
label: z.string().describe("Human-readable field label"),
|
|
26
|
+
required: z.boolean().optional(),
|
|
27
|
+
placeholder: z.string().optional(),
|
|
28
|
+
description: z.string().optional(),
|
|
29
|
+
options: z.array(Option).optional().describe("Required for radio, select, checkbox_group"),
|
|
30
|
+
file: FileConfig.describe("Optional config for file fields"),
|
|
31
|
+
validation: FieldValidation,
|
|
32
|
+
});
|
|
33
|
+
export function registerCreateForm(server, client) {
|
|
34
|
+
server.tool("create_form", `Create a LetsClarify form. Returns a form_token, delete_token, recipient UUIDs, and URL template.
|
|
35
|
+
Build shareable URLs by replacing {recipient_uuid} in base_url_template with each UUID.
|
|
36
|
+
Use the "letsclarify://schema-dsl" resource for field type reference.`, {
|
|
37
|
+
schema: z.array(SchemaField).min(1).max(50).describe("Form field definitions (1–50 fields)"),
|
|
38
|
+
title: z.string().optional().describe("Form title shown to recipients"),
|
|
39
|
+
context_markdown: z.string().optional().describe("Markdown context shown above the form"),
|
|
40
|
+
recipient_count: z.number().int().min(1).max(1000).optional().describe("Number of recipient slots (default: 1)"),
|
|
41
|
+
retention_days: z.number().int().min(1).max(365).optional().describe("Days until auto-deletion (default: 30)"),
|
|
42
|
+
webhook_url: z.string().optional().describe("HTTPS URL for submission webhooks"),
|
|
43
|
+
theme_color: z.string().optional().describe("Hex color for form branding, e.g. #1a2b3c"),
|
|
44
|
+
}, async (args) => {
|
|
45
|
+
try {
|
|
46
|
+
const result = await client.createForm({
|
|
47
|
+
schema: args.schema,
|
|
48
|
+
title: args.title,
|
|
49
|
+
context_markdown: args.context_markdown,
|
|
50
|
+
recipient_count: args.recipient_count,
|
|
51
|
+
retention_days: args.retention_days,
|
|
52
|
+
webhook_url: args.webhook_url,
|
|
53
|
+
theme_color: args.theme_color,
|
|
54
|
+
});
|
|
55
|
+
const urls = result.recipients.map((uuid) => result.base_url_template.replace("{recipient_uuid}", uuid));
|
|
56
|
+
return {
|
|
57
|
+
content: [
|
|
58
|
+
{
|
|
59
|
+
type: "text",
|
|
60
|
+
text: JSON.stringify({
|
|
61
|
+
form_token: result.form_token,
|
|
62
|
+
delete_token: result.delete_token,
|
|
63
|
+
recipient_urls: urls,
|
|
64
|
+
poll_url: result.poll_url,
|
|
65
|
+
summary_url: result.summary_url,
|
|
66
|
+
}, null, 2),
|
|
67
|
+
},
|
|
68
|
+
],
|
|
69
|
+
};
|
|
70
|
+
}
|
|
71
|
+
catch (error) {
|
|
72
|
+
return {
|
|
73
|
+
content: [{ type: "text", text: `Error: ${error instanceof Error ? error.message : String(error)}` }],
|
|
74
|
+
isError: true,
|
|
75
|
+
};
|
|
76
|
+
}
|
|
77
|
+
});
|
|
78
|
+
}
|
|
79
|
+
//# sourceMappingURL=create-form.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"create-form.js","sourceRoot":"","sources":["../../src/tools/create-form.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"delete-form.d.ts","sourceRoot":"","sources":["../../src/tools/delete-form.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,MAAM,yCAAyC,CAAC;AAEpE,OAAO,EAAE,iBAAiB,EAAE,MAAM,cAAc,CAAC;AAEjD,wBAAgB,kBAAkB,CAAC,MAAM,EAAE,SAAS,EAAE,MAAM,EAAE,iBAAiB,QAsB9E"}
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import { z } from "zod";
|
|
2
|
+
export function registerDeleteForm(server, client) {
|
|
3
|
+
server.tool("delete_form", "Permanently delete a form and all its data (recipients, submissions, files). This action is irreversible. Requires the delete_token from the create_form response.", {
|
|
4
|
+
form_token: z.string().describe("The form token returned by create_form"),
|
|
5
|
+
delete_token: z.string().describe("The delete token returned by create_form"),
|
|
6
|
+
}, async (args) => {
|
|
7
|
+
try {
|
|
8
|
+
const result = await client.deleteForm(args.form_token, args.delete_token);
|
|
9
|
+
return {
|
|
10
|
+
content: [{ type: "text", text: JSON.stringify(result, null, 2) }],
|
|
11
|
+
};
|
|
12
|
+
}
|
|
13
|
+
catch (error) {
|
|
14
|
+
return {
|
|
15
|
+
content: [{ type: "text", text: `Error: ${error instanceof Error ? error.message : String(error)}` }],
|
|
16
|
+
isError: true,
|
|
17
|
+
};
|
|
18
|
+
}
|
|
19
|
+
});
|
|
20
|
+
}
|
|
21
|
+
//# sourceMappingURL=delete-form.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"delete-form.js","sourceRoot":"","sources":["../../src/tools/delete-form.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAGxB,MAAM,UAAU,kBAAkB,CAAC,MAAiB,EAAE,MAAyB;IAC7E,MAAM,CAAC,IAAI,CACT,aAAa,EACb,oKAAoK,EACpK;QACE,UAAU,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,CAAC,wCAAwC,CAAC;QACzE,YAAY,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,CAAC,0CAA0C,CAAC;KAC9E,EACD,KAAK,EAAE,IAAI,EAAE,EAAE;QACb,IAAI,CAAC;YACH,MAAM,MAAM,GAAG,MAAM,MAAM,CAAC,UAAU,CAAC,IAAI,CAAC,UAAU,EAAE,IAAI,CAAC,YAAY,CAAC,CAAC;YAC3E,OAAO;gBACL,OAAO,EAAE,CAAC,EAAE,IAAI,EAAE,MAAe,EAAE,IAAI,EAAE,IAAI,CAAC,SAAS,CAAC,MAAM,EAAE,IAAI,EAAE,CAAC,CAAC,EAAE,CAAC;aAC5E,CAAC;QACJ,CAAC;QAAC,OAAO,KAAK,EAAE,CAAC;YACf,OAAO;gBACL,OAAO,EAAE,CAAC,EAAE,IAAI,EAAE,MAAe,EAAE,IAAI,EAAE,UAAU,KAAK,YAAY,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,EAAE,EAAE,CAAC;gBAC9G,OAAO,EAAE,IAAI;aACd,CAAC;QACJ,CAAC;IACH,CAAC,CACF,CAAC;AACJ,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"get-form-results.d.ts","sourceRoot":"","sources":["../../src/tools/get-form-results.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,MAAM,yCAAyC,CAAC;AAEpE,OAAO,EAAE,iBAAiB,EAAE,MAAM,cAAc,CAAC;AAEjD,wBAAgB,sBAAsB,CAAC,MAAM,EAAE,SAAS,EAAE,MAAM,EAAE,iBAAiB,QAkClF"}
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
import { z } from "zod";
|
|
2
|
+
export function registerGetFormResults(server, client) {
|
|
3
|
+
server.tool("get_form_results", "Fetch paginated form results. Returns each recipient's status and submitted answers. Supports filtering by status and updated_since for efficient polling.", {
|
|
4
|
+
form_token: z.string().describe("The form token returned by create_form"),
|
|
5
|
+
limit: z.number().int().min(1).max(1000).optional().describe("Max results per page (default: 100)"),
|
|
6
|
+
cursor: z.string().optional().describe("Pagination cursor from a previous response"),
|
|
7
|
+
status: z.enum(["submitted", "pending"]).optional().describe("Filter by recipient status"),
|
|
8
|
+
updated_since: z.string().optional().describe("ISO8601 timestamp — only return results updated at or after this time"),
|
|
9
|
+
include_files: z.boolean().optional().describe("Include base64-encoded file contents (can be large)"),
|
|
10
|
+
}, async (args) => {
|
|
11
|
+
try {
|
|
12
|
+
const params = {
|
|
13
|
+
limit: args.limit?.toString(),
|
|
14
|
+
cursor: args.cursor,
|
|
15
|
+
status: args.status,
|
|
16
|
+
updated_since: args.updated_since,
|
|
17
|
+
include_files: args.include_files ? "1" : undefined,
|
|
18
|
+
};
|
|
19
|
+
const result = await client.getFormResults(args.form_token, params);
|
|
20
|
+
return {
|
|
21
|
+
content: [{ type: "text", text: JSON.stringify(result, null, 2) }],
|
|
22
|
+
};
|
|
23
|
+
}
|
|
24
|
+
catch (error) {
|
|
25
|
+
return {
|
|
26
|
+
content: [{ type: "text", text: `Error: ${error instanceof Error ? error.message : String(error)}` }],
|
|
27
|
+
isError: true,
|
|
28
|
+
};
|
|
29
|
+
}
|
|
30
|
+
});
|
|
31
|
+
}
|
|
32
|
+
//# sourceMappingURL=get-form-results.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"get-form-results.js","sourceRoot":"","sources":["../../src/tools/get-form-results.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAGxB,MAAM,UAAU,sBAAsB,CAAC,MAAiB,EAAE,MAAyB;IACjF,MAAM,CAAC,IAAI,CACT,kBAAkB,EAClB,4JAA4J,EAC5J;QACE,UAAU,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,CAAC,wCAAwC,CAAC;QACzE,KAAK,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,GAAG,EAAE,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC,QAAQ,EAAE,CAAC,QAAQ,CAAC,qCAAqC,CAAC;QACnG,MAAM,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,EAAE,CAAC,QAAQ,CAAC,4CAA4C,CAAC;QACpF,MAAM,EAAE,CAAC,CAAC,IAAI,CAAC,CAAC,WAAW,EAAE,SAAS,CAAC,CAAC,CAAC,QAAQ,EAAE,CAAC,QAAQ,CAAC,4BAA4B,CAAC;QAC1F,aAAa,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,EAAE,CAAC,QAAQ,CAAC,uEAAuE,CAAC;QACtH,aAAa,EAAE,CAAC,CAAC,OAAO,EAAE,CAAC,QAAQ,EAAE,CAAC,QAAQ,CAAC,qDAAqD,CAAC;KACtG,EACD,KAAK,EAAE,IAAI,EAAE,EAAE;QACb,IAAI,CAAC;YACH,MAAM,MAAM,GAAuC;gBACjD,KAAK,EAAE,IAAI,CAAC,KAAK,EAAE,QAAQ,EAAE;gBAC7B,MAAM,EAAE,IAAI,CAAC,MAAM;gBACnB,MAAM,EAAE,IAAI,CAAC,MAAM;gBACnB,aAAa,EAAE,IAAI,CAAC,aAAa;gBACjC,aAAa,EAAE,IAAI,CAAC,aAAa,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,SAAS;aACpD,CAAC;YAEF,MAAM,MAAM,GAAG,MAAM,MAAM,CAAC,cAAc,CAAC,IAAI,CAAC,UAAU,EAAE,MAAM,CAAC,CAAC;YACpE,OAAO;gBACL,OAAO,EAAE,CAAC,EAAE,IAAI,EAAE,MAAe,EAAE,IAAI,EAAE,IAAI,CAAC,SAAS,CAAC,MAAM,EAAE,IAAI,EAAE,CAAC,CAAC,EAAE,CAAC;aAC5E,CAAC;QACJ,CAAC;QAAC,OAAO,KAAK,EAAE,CAAC;YACf,OAAO;gBACL,OAAO,EAAE,CAAC,EAAE,IAAI,EAAE,MAAe,EAAE,IAAI,EAAE,UAAU,KAAK,YAAY,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,EAAE,EAAE,CAAC;gBAC9G,OAAO,EAAE,IAAI;aACd,CAAC;QACJ,CAAC;IACH,CAAC,CACF,CAAC;AACJ,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"get-form-summary.d.ts","sourceRoot":"","sources":["../../src/tools/get-form-summary.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,MAAM,yCAAyC,CAAC;AAEpE,OAAO,EAAE,iBAAiB,EAAE,MAAM,cAAc,CAAC;AAEjD,wBAAgB,sBAAsB,CAAC,MAAM,EAAE,SAAS,EAAE,MAAM,EAAE,iBAAiB,QAqBlF"}
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import { z } from "zod";
|
|
2
|
+
export function registerGetFormSummary(server, client) {
|
|
3
|
+
server.tool("get_form_summary", "Get a quick overview of a form: how many recipients submitted vs. pending, and whether the form is expired.", {
|
|
4
|
+
form_token: z.string().describe("The form token returned by create_form"),
|
|
5
|
+
}, async (args) => {
|
|
6
|
+
try {
|
|
7
|
+
const result = await client.getFormSummary(args.form_token);
|
|
8
|
+
return {
|
|
9
|
+
content: [{ type: "text", text: JSON.stringify(result, null, 2) }],
|
|
10
|
+
};
|
|
11
|
+
}
|
|
12
|
+
catch (error) {
|
|
13
|
+
return {
|
|
14
|
+
content: [{ type: "text", text: `Error: ${error instanceof Error ? error.message : String(error)}` }],
|
|
15
|
+
isError: true,
|
|
16
|
+
};
|
|
17
|
+
}
|
|
18
|
+
});
|
|
19
|
+
}
|
|
20
|
+
//# sourceMappingURL=get-form-summary.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"get-form-summary.js","sourceRoot":"","sources":["../../src/tools/get-form-summary.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAGxB,MAAM,UAAU,sBAAsB,CAAC,MAAiB,EAAE,MAAyB;IACjF,MAAM,CAAC,IAAI,CACT,kBAAkB,EAClB,6GAA6G,EAC7G;QACE,UAAU,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,CAAC,wCAAwC,CAAC;KAC1E,EACD,KAAK,EAAE,IAAI,EAAE,EAAE;QACb,IAAI,CAAC;YACH,MAAM,MAAM,GAAG,MAAM,MAAM,CAAC,cAAc,CAAC,IAAI,CAAC,UAAU,CAAC,CAAC;YAC5D,OAAO;gBACL,OAAO,EAAE,CAAC,EAAE,IAAI,EAAE,MAAe,EAAE,IAAI,EAAE,IAAI,CAAC,SAAS,CAAC,MAAM,EAAE,IAAI,EAAE,CAAC,CAAC,EAAE,CAAC;aAC5E,CAAC;QACJ,CAAC;QAAC,OAAO,KAAK,EAAE,CAAC;YACf,OAAO;gBACL,OAAO,EAAE,CAAC,EAAE,IAAI,EAAE,MAAe,EAAE,IAAI,EAAE,UAAU,KAAK,YAAY,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,EAAE,EAAE,CAAC;gBAC9G,OAAO,EAAE,IAAI;aACd,CAAC;QACJ,CAAC;IACH,CAAC,CACF,CAAC;AACJ,CAAC"}
|
package/package.json
ADDED
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@heisee/letsclarify-mcp",
|
|
3
|
+
"version": "1.0.0",
|
|
4
|
+
"description": "MCP server for LetsClarify — Human-in-the-Loop API for AI agents",
|
|
5
|
+
"license": "MIT",
|
|
6
|
+
"author": "heisee",
|
|
7
|
+
"repository": {
|
|
8
|
+
"type": "git",
|
|
9
|
+
"url": "https://github.com/heisee/LetsClarify",
|
|
10
|
+
"directory": "mcp-server"
|
|
11
|
+
},
|
|
12
|
+
"type": "module",
|
|
13
|
+
"main": "build/index.js",
|
|
14
|
+
"bin": {
|
|
15
|
+
"letsclarify-mcp": "build/index.js"
|
|
16
|
+
},
|
|
17
|
+
"files": [
|
|
18
|
+
"build"
|
|
19
|
+
],
|
|
20
|
+
"scripts": {
|
|
21
|
+
"build": "tsc",
|
|
22
|
+
"prepublishOnly": "npm run build"
|
|
23
|
+
},
|
|
24
|
+
"keywords": [
|
|
25
|
+
"mcp",
|
|
26
|
+
"model-context-protocol",
|
|
27
|
+
"letsclarify",
|
|
28
|
+
"human-in-the-loop",
|
|
29
|
+
"ai-agents",
|
|
30
|
+
"forms"
|
|
31
|
+
],
|
|
32
|
+
"engines": {
|
|
33
|
+
"node": ">=18"
|
|
34
|
+
},
|
|
35
|
+
"dependencies": {
|
|
36
|
+
"@modelcontextprotocol/sdk": "^1.12.1",
|
|
37
|
+
"zod": "^3.25.1"
|
|
38
|
+
},
|
|
39
|
+
"devDependencies": {
|
|
40
|
+
"@types/node": "^22.15.21",
|
|
41
|
+
"typescript": "^5.8.3"
|
|
42
|
+
}
|
|
43
|
+
}
|