@chaprola/mcp-server 1.0.1 → 1.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 +7 -2
- package/dist/index.js +60 -11
- package/package.json +2 -2
- package/references/cookbook.md +1 -1
- package/references/endpoints.md +1 -1
- package/references/gotchas.md +2 -2
package/README.md
CHANGED
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
|
|
3
3
|
MCP server for [Chaprola](https://chaprola.org) — the agent-first data platform.
|
|
4
4
|
|
|
5
|
-
Gives AI agents
|
|
5
|
+
Gives AI agents 40 tools for structured data storage, querying, web search, URL fetching, scheduled jobs, and execution through the [Model Context Protocol](https://modelcontextprotocol.io).
|
|
6
6
|
|
|
7
7
|
## Quick Start
|
|
8
8
|
|
|
@@ -116,13 +116,18 @@ Or use the `chaprola_register` tool after connecting.
|
|
|
116
116
|
| `chaprola_email_read` | Read email |
|
|
117
117
|
| `chaprola_email_send` | Send email |
|
|
118
118
|
| `chaprola_email_delete` | Delete email |
|
|
119
|
+
| `chaprola_search` | Web search via Brave API |
|
|
120
|
+
| `chaprola_fetch` | Fetch URL content as markdown/text/JSON |
|
|
121
|
+
| `chaprola_schedule` | Create scheduled recurring job |
|
|
122
|
+
| `chaprola_schedule_list` | List scheduled jobs |
|
|
123
|
+
| `chaprola_schedule_delete` | Delete scheduled job |
|
|
119
124
|
|
|
120
125
|
## Resources
|
|
121
126
|
|
|
122
127
|
The server exposes reference documentation as MCP resources:
|
|
123
128
|
|
|
124
129
|
- `chaprola://cookbook` — Language cookbook with complete examples
|
|
125
|
-
- `chaprola://endpoints` — All
|
|
130
|
+
- `chaprola://endpoints` — All 40 API endpoints
|
|
126
131
|
- `chaprola://auth` — Authentication reference
|
|
127
132
|
- `chaprola://gotchas` — Common mistakes to avoid
|
|
128
133
|
|
package/dist/index.js
CHANGED
|
@@ -121,7 +121,7 @@ server.resource("cookbook", "chaprola://cookbook", { description: "Chaprola lang
|
|
|
121
121
|
server.resource("gotchas", "chaprola://gotchas", { description: "Common Chaprola mistakes — no parentheses in LET, no commas in PRINT, MOVE length must match field width, DEFINE names must not collide with fields. READ THIS before writing code.", mimeType: "text/markdown" }, async () => ({
|
|
122
122
|
contents: [{ uri: "chaprola://gotchas", mimeType: "text/markdown", text: readRef("gotchas.md") }],
|
|
123
123
|
}));
|
|
124
|
-
server.resource("endpoints", "chaprola://endpoints", { description: "Chaprola API endpoint reference — all
|
|
124
|
+
server.resource("endpoints", "chaprola://endpoints", { description: "Chaprola API endpoint reference — all 40 endpoints with request/response shapes", mimeType: "text/markdown" }, async () => ({
|
|
125
125
|
contents: [{ uri: "chaprola://endpoints", mimeType: "text/markdown", text: readRef("endpoints.md") }],
|
|
126
126
|
}));
|
|
127
127
|
server.resource("auth", "chaprola://auth", { description: "Chaprola authentication reference — API key model, BAA flow, credential recovery", mimeType: "text/markdown" }, async () => ({
|
|
@@ -201,15 +201,12 @@ server.tool("chaprola_baa_text", "Get the current Business Associate Agreement t
|
|
|
201
201
|
const res = await publicFetch("POST", "/baa-text", {});
|
|
202
202
|
return textResult(res);
|
|
203
203
|
});
|
|
204
|
-
server.tool("chaprola_report", "Run a published program and return output. No auth required — program must be published first", {
|
|
204
|
+
server.tool("chaprola_report", "Run a published program and return output. No auth required — program must be published first via /publish", {
|
|
205
205
|
userid: z.string().describe("Owner of the published program"),
|
|
206
206
|
project: z.string().describe("Project containing the program"),
|
|
207
207
|
name: z.string().describe("Name of the published .PR file"),
|
|
208
|
-
|
|
209
|
-
}, async ({ userid, project, name, primary_file }) => {
|
|
208
|
+
}, async ({ userid, project, name }) => {
|
|
210
209
|
const body = { userid, project, name };
|
|
211
|
-
if (primary_file)
|
|
212
|
-
body.primary_file = primary_file;
|
|
213
210
|
const res = await publicFetch("POST", "/report", body);
|
|
214
211
|
return textResult(res);
|
|
215
212
|
});
|
|
@@ -311,19 +308,19 @@ server.tool("chaprola_list", "List files in a project with optional wildcard pat
|
|
|
311
308
|
return textResult(res);
|
|
312
309
|
}));
|
|
313
310
|
// --- Compile ---
|
|
314
|
-
server.tool("chaprola_compile", "Compile Chaprola source (.CS) to bytecode (.PR). READ chaprola://cookbook BEFORE writing source. Key syntax: no PROGRAM keyword (start with commands), no commas, MOVE+PRINT 0 buffer model (not PRINT field), SEEK for primary records, OPEN/READ/WRITE/CLOSE for secondary files, LET supports one operation (no parentheses), field addressing via P.field/S.field requires primary_format/
|
|
311
|
+
server.tool("chaprola_compile", "Compile Chaprola source (.CS) to bytecode (.PR). READ chaprola://cookbook BEFORE writing source. Key syntax: no PROGRAM keyword (start with commands), no commas, MOVE+PRINT 0 buffer model (not PRINT field), SEEK for primary records, OPEN/READ/WRITE/CLOSE for secondary files, LET supports one operation (no parentheses), field addressing via P.field/S.field requires primary_format/secondary_format params.", {
|
|
315
312
|
project: z.string().describe("Project name"),
|
|
316
313
|
name: z.string().describe("Program name (without extension)"),
|
|
317
314
|
source: z.string().describe("Chaprola source code"),
|
|
318
315
|
primary_format: z.string().optional().describe("Primary data file name (enables P.fieldname addressing)"),
|
|
319
|
-
|
|
320
|
-
}, async ({ project, name, source, primary_format,
|
|
316
|
+
secondary_format: z.string().optional().describe("Secondary format file name (enables S.fieldname addressing)"),
|
|
317
|
+
}, async ({ project, name, source, primary_format, secondary_format }) => withBaaCheck(async () => {
|
|
321
318
|
const { username } = getCredentials();
|
|
322
319
|
const body = { userid: username, project, name, source };
|
|
323
320
|
if (primary_format)
|
|
324
321
|
body.primary_format = primary_format;
|
|
325
|
-
if (
|
|
326
|
-
body.
|
|
322
|
+
if (secondary_format)
|
|
323
|
+
body.secondary_format = secondary_format;
|
|
327
324
|
const res = await authedFetch("/compile", body);
|
|
328
325
|
return textResult(res);
|
|
329
326
|
}));
|
|
@@ -576,6 +573,58 @@ server.tool("chaprola_email_delete", "Delete a specific email from your mailbox"
|
|
|
576
573
|
const res = await authedFetch("/email/delete", { address: username, message_id });
|
|
577
574
|
return textResult(res);
|
|
578
575
|
}));
|
|
576
|
+
// --- Search ---
|
|
577
|
+
server.tool("chaprola_search", "Search the web via Brave Search API. Returns titles, URLs, and snippets. Optional AI-grounded summary. Rate limit: 10/day per user", {
|
|
578
|
+
query: z.string().describe("Search query string"),
|
|
579
|
+
count: z.number().optional().describe("Number of results to return (default 5, max 20)"),
|
|
580
|
+
summarize: z.boolean().optional().describe("Include AI-grounded summary from Brave Answers API"),
|
|
581
|
+
}, async ({ query, count, summarize }) => withBaaCheck(async () => {
|
|
582
|
+
const body = { query };
|
|
583
|
+
if (count !== undefined)
|
|
584
|
+
body.count = count;
|
|
585
|
+
if (summarize !== undefined)
|
|
586
|
+
body.summarize = summarize;
|
|
587
|
+
const res = await authedFetch("/search", body);
|
|
588
|
+
return textResult(res);
|
|
589
|
+
}));
|
|
590
|
+
// --- Fetch ---
|
|
591
|
+
server.tool("chaprola_fetch", "Fetch any URL and return clean content. HTML pages converted to markdown. SSRF-protected. Rate limit: 20/day per user", {
|
|
592
|
+
url: z.string().url().describe("URL to fetch (http:// or https://)"),
|
|
593
|
+
format: z.enum(["markdown", "text", "html", "json"]).optional().describe("Output format (default: markdown)"),
|
|
594
|
+
max_length: z.number().optional().describe("Max output characters (default: 50000, max: 200000)"),
|
|
595
|
+
}, async ({ url, format, max_length }) => withBaaCheck(async () => {
|
|
596
|
+
const body = { url };
|
|
597
|
+
if (format)
|
|
598
|
+
body.format = format;
|
|
599
|
+
if (max_length !== undefined)
|
|
600
|
+
body.max_length = max_length;
|
|
601
|
+
const res = await authedFetch("/fetch", body);
|
|
602
|
+
return textResult(res);
|
|
603
|
+
}));
|
|
604
|
+
// --- Schedule ---
|
|
605
|
+
server.tool("chaprola_schedule", "Create a scheduled job that runs a Chaprola endpoint on a recurring cron. Max 10 schedules/user, 15-min minimum interval", {
|
|
606
|
+
name: z.string().describe("Unique name for this schedule (alphanumeric + hyphens/underscores)"),
|
|
607
|
+
cron: z.string().describe("Standard 5-field cron expression (min hour day month weekday). Minimum interval: 15 minutes"),
|
|
608
|
+
endpoint: z.enum(["/import-download", "/run", "/export-report", "/search", "/fetch", "/query", "/email/send", "/export", "/report", "/list"]).describe("Target endpoint to call"),
|
|
609
|
+
body: z.record(z.any()).describe("Request body for the target endpoint. userid is injected automatically"),
|
|
610
|
+
skip_if_unchanged: z.boolean().optional().describe("Skip when response matches previous run (SHA-256 hash). Default: false"),
|
|
611
|
+
}, async ({ name, cron, endpoint, body, skip_if_unchanged }) => withBaaCheck(async () => {
|
|
612
|
+
const reqBody = { name, cron, endpoint, body };
|
|
613
|
+
if (skip_if_unchanged !== undefined)
|
|
614
|
+
reqBody.skip_if_unchanged = skip_if_unchanged;
|
|
615
|
+
const res = await authedFetch("/schedule", reqBody);
|
|
616
|
+
return textResult(res);
|
|
617
|
+
}));
|
|
618
|
+
server.tool("chaprola_schedule_list", "List all scheduled jobs for the authenticated user with run history and next execution time", {}, async () => withBaaCheck(async () => {
|
|
619
|
+
const res = await authedFetch("/schedule/list", {});
|
|
620
|
+
return textResult(res);
|
|
621
|
+
}));
|
|
622
|
+
server.tool("chaprola_schedule_delete", "Delete a scheduled job by name", {
|
|
623
|
+
name: z.string().describe("Name of the schedule to delete"),
|
|
624
|
+
}, async ({ name }) => withBaaCheck(async () => {
|
|
625
|
+
const res = await authedFetch("/schedule/delete", { name });
|
|
626
|
+
return textResult(res);
|
|
627
|
+
}));
|
|
579
628
|
// --- Start server ---
|
|
580
629
|
async function main() {
|
|
581
630
|
const transport = new StdioServerTransport();
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@chaprola/mcp-server",
|
|
3
|
-
"version": "1.0
|
|
4
|
-
"description": "MCP server for Chaprola — agent-first data platform. Gives AI agents
|
|
3
|
+
"version": "1.1.0",
|
|
4
|
+
"description": "MCP server for Chaprola — agent-first data platform. Gives AI agents 40 tools for structured data storage, querying, web search, URL fetching, scheduled jobs, and execution via plain HTTP.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "dist/index.js",
|
|
7
7
|
"bin": {
|
package/references/cookbook.md
CHANGED
|
@@ -58,7 +58,7 @@ READ match // load matched secondary record
|
|
|
58
58
|
MOVE S.dept_name U.12 15 // now accessible
|
|
59
59
|
```
|
|
60
60
|
|
|
61
|
-
Compile with: `primary_format: "EMPLOYEES",
|
|
61
|
+
Compile with: `primary_format: "EMPLOYEES", secondary_format: "DEPARTMENTS"`
|
|
62
62
|
|
|
63
63
|
## Read-Modify-Write (UPDATE)
|
|
64
64
|
|
package/references/endpoints.md
CHANGED
|
@@ -38,7 +38,7 @@ Auth: `Authorization: Bearer chp_your_api_key` on all protected endpoints.
|
|
|
38
38
|
### Compile & Run
|
|
39
39
|
| Endpoint | Body | Response |
|
|
40
40
|
|----------|------|----------|
|
|
41
|
-
| `POST /compile` | `{userid, project, name, source, primary_format?,
|
|
41
|
+
| `POST /compile` | `{userid, project, name, source, primary_format?, secondary_format?}` | `{instructions, bytes}` |
|
|
42
42
|
| `POST /run` | `{userid, project, name, primary_file?, record?, async?, nophi?}` | `{output, registers}` or `{job_id}` |
|
|
43
43
|
| `POST /run/status` | `{userid, project, job_id}` | `{status: "running"/"done", output?}` |
|
|
44
44
|
| `POST /publish` | `{userid, project, name, primary_file?, record?}` | `{report_url}` |
|
package/references/gotchas.md
CHANGED
|
@@ -58,8 +58,8 @@ All import/export/compile/run/query/email endpoints return 403 without a signed
|
|
|
58
58
|
### Async for large datasets
|
|
59
59
|
`POST /run` with `async: true` for >100K records. API Gateway has a 30-second timeout; async bypasses it. Poll `/run/status` until `status: "done"`.
|
|
60
60
|
|
|
61
|
-
###
|
|
62
|
-
Pass `
|
|
61
|
+
### secondary_format is a string
|
|
62
|
+
Pass `secondary_format: "DEPARTMENTS"` (a single string), not an array, to `/compile`.
|
|
63
63
|
|
|
64
64
|
### Data files expire
|
|
65
65
|
Default 90 days. Set `expires_in_days` on import to override. Expired files are deleted daily at 03:00 UTC.
|