Sign In

@getabrain/mcp-server

Package Overview
Dependencies
Maintainers
1
Versions
8
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

@getabrain/mcp-server - npm Package Compare versions

Comparing version
0.2.0
to
0.2.1
logo.png

Sorry, the diff of this file is not supported yet

+85
-9

@@ -34,3 +34,8 @@ #!/usr/bin/env node

function ok(data) {
return { content: [{ type: "text", text: typeof data === "string" ? data : JSON.stringify(data) }] };
const text = typeof data === "string" ? data : JSON.stringify(data);
const res = { content: [{ type: "text", text }] };
if (data !== null && typeof data === "object" && !Array.isArray(data)) {
res.structuredContent = data;
}
return res;
}

@@ -62,2 +67,11 @@ function fail(message) {

inputShape: {},
annotations: { title: "Check prepaid balance", readOnlyHint: true, openWorldHint: true },
outputShape: {
balance_cents: z.number().optional(),
company_name: z.string().optional(),
mode: z.string().optional(),
auto_reload_enabled: z.boolean().optional(),
auto_reload_setup_url: z.string().optional(),
hint: z.string().optional()
},
run: async (_args, client) => {

@@ -83,2 +97,10 @@ const b = await client.account.balance();

},
annotations: {
title: "Create top-up payment link",
readOnlyHint: false,
destructiveHint: false,
idempotentHint: false,
openWorldHint: true
},
outputShape: { checkout_url: z.string().optional() },
run: async (args, client) => ok(await client.account.createTopupLink(args.amount_cents))

@@ -97,3 +119,3 @@ },

bid_amount_cents: z.number().int().min(5).max(1e7).describe(
"Cents paid to EACH worker per accepted response (min 5 = $0.05, max 10000000 = $100,000.00). Total cost = (bid_amount_cents + bonus_amount_cents) * required_responses, deducted from balance in live mode. No charge occurs in test mode."
"Cents paid to EACH worker per accepted response (absolute floor 5 = $0.05, max 10000000 = $100,000.00). The REAL minimum is effort-based, not flat: it scales with how long the query type honestly takes a worker to answer, priced at a fair ~$9/hr (0.25 cents/second). Quick types (yes_no, multiple_choice, sentiment, ab_test, headline_test, rating_scale) floor around 5 cents; medium types (image_comparison, image_selection, ranking, text, image_analysis) around 8-12 cents; capture types (voice_capture, photo_capture, custom) around 15 cents; longer types (free_form_text, video_capture) around 30 cents. video_review and audio_review scale with the actual clip length (content_data.video_duration_seconds / audio_duration_seconds) plus a review/write-up overhead, so a 10-minute video review requires roughly $1.65+ -- there is no upper cap, longer clips need proportionally higher bids. Bidding below the type-appropriate minimum is rejected with a 400 telling you the exact floor; call GET /requestor/suggested-bid?type=... for the current min_bid_cents and suggested_bid_cents for a given type before submitting. Total cost = (bid_amount_cents + bonus_amount_cents) * required_responses, deducted from balance in live mode. No charge occurs in test mode."
),

@@ -104,2 +126,17 @@ description: z.string().optional().describe("Optional longer explanation/context shown to workers alongside the title, for extra instructions or background."),

},
annotations: {
title: "Ask human workers a question",
readOnlyHint: false,
destructiveHint: false,
idempotentHint: false,
openWorldHint: true
},
outputShape: {
query_id: z.string().optional(),
id: z.string().optional(),
status: z.string().optional(),
required_responses: z.number().optional(),
total_cost_cents: z.number().optional(),
simulated: z.boolean().optional()
},
run: async (args, client) => ok(await client.queries.create(args))

@@ -113,2 +150,9 @@ },

},
annotations: { title: "Get query responses", readOnlyHint: true, openWorldHint: true },
outputShape: {
status: z.string().optional(),
completed_responses: z.number().optional(),
required_responses: z.number().optional(),
responses: z.array(z.any()).optional()
},
run: async (args, client) => {

@@ -132,2 +176,10 @@ const q = await client.queries.get(args.query_id);

},
annotations: { title: "Wait for human responses", readOnlyHint: true, openWorldHint: true },
outputShape: {
status: z.string().optional(),
responses: z.array(z.any()).optional(),
completed_responses: z.number().optional(),
required_responses: z.number().optional(),
hint: z.string().optional()
},
run: async (args, client) => {

@@ -165,2 +217,10 @@ const current = await client.queries.get(args.query_id);

},
annotations: { title: "List your queries", readOnlyHint: true, openWorldHint: true },
outputShape: {
queries: z.array(z.any()).optional(),
total: z.number().optional(),
limit: z.number().optional(),
offset: z.number().optional(),
has_more: z.boolean().optional()
},
run: async (args, client) => ok(await client.queries.list(args))

@@ -177,2 +237,14 @@ },

},
annotations: {
title: "Rate a worker response",
readOnlyHint: false,
destructiveHint: false,
idempotentHint: false,
openWorldHint: true
},
outputShape: {
worker_quality_score: z.number().optional(),
success: z.boolean().optional(),
message: z.string().optional()
},
run: async (args, client) => ok(await client.responses.rate(args.query_id, args.response_id, { score: args.score, feedback_text: args.feedback_text }))

@@ -184,11 +256,15 @@ }

function createServer(client) {
const server = new McpServer({ name: "getabrain", version: "0.1.0" });
const server = new McpServer({ name: "getabrain", version: "0.2.1" });
for (const t of tools) {
server.tool(t.name, t.description, t.inputShape, async (args) => {
try {
return await t.run(args, client);
} catch (e) {
return toToolError(e);
server.registerTool(
t.name,
{ description: t.description, inputSchema: t.inputShape, outputSchema: t.outputShape, annotations: t.annotations },
async (args) => {
try {
return await t.run(args, client);
} catch (e) {
return toToolError(e);
}
}
});
);
}

@@ -195,0 +271,0 @@ return server;

+7
-4
{
"name": "@getabrain/mcp-server",
"version": "0.2.0",
"version": "0.2.1",
"description": "MCP server for GetABrain.ai \u2014 real human judgment as agent tools",

@@ -12,6 +12,7 @@ "type": "module",

"dist",
"README.md"
"README.md",
"logo.png"
],
"scripts": {
"build": "tsup src/index.ts --format esm --dts --clean --tsconfig tsconfig.build.json",
"build": "tsup src/index.ts --format esm --clean --tsconfig tsconfig.build.json",
"prepublishOnly": "npm run build"

@@ -28,3 +29,5 @@ },

"devDependencies": {
"tsup": "^8.0.0"
"@types/node": "^22",
"tsup": "^8.0.0",
"typescript": "^5"
},

@@ -31,0 +34,0 @@ "license": "MIT",

@@ -0,1 +1,5 @@

<p align="center">
<img src="./logo.png" alt="GetABrain" width="128" height="128" />
</p>
# @getabrain/mcp-server

@@ -26,2 +30,25 @@

## Remote (hosted) MCP server -- no install
Prefer not to run anything locally? GetABrain also hosts this same server over Streamable HTTP at
`https://www.getabrain.ai/api/mcp`. Point any MCP client that supports remote servers at that URL and
pass your key pair as headers instead of env vars:
```json
{
"mcpServers": {
"getabrain": {
"url": "https://www.getabrain.ai/api/mcp",
"headers": {
"X-API-Key": "gab_k_…",
"X-API-Secret": "gab_s_…"
}
}
}
}
```
Same 7 tools, same schemas, same test-mode support -- see `docs/deploy/remote-mcp.md` in this repo for
details (Smithery-style clients, auth requirements, etc).
## Test mode

@@ -28,0 +55,0 @@

#!/usr/bin/env node