@humanops/mcp-server 0.3.2 → 0.3.3
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/dist/index.js +191 -4
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -522,7 +522,10 @@ const PostTaskInputSchema = z.object({
|
|
|
522
522
|
lng: z.number(),
|
|
523
523
|
address: z.string().min(1),
|
|
524
524
|
}),
|
|
525
|
-
|
|
525
|
+
urgency: z.enum(["standard", "priority", "urgent"]).optional(),
|
|
526
|
+
reward_usd: z.number().min(MIN_TASK_VALUE_USD).max(MAX_TASK_VALUE_USD).optional(),
|
|
527
|
+
max_budget_usd: z.number().min(MIN_TASK_VALUE_USD).max(MAX_TASK_VALUE_USD).optional(),
|
|
528
|
+
proposal_deadline_minutes: z.number().int().min(15).max(10080).optional(),
|
|
526
529
|
deadline: z.string().datetime(),
|
|
527
530
|
proof_requirements: z.array(z.string().min(1).max(500)).min(1).max(10),
|
|
528
531
|
task_type: TaskTypeEnum,
|
|
@@ -535,10 +538,37 @@ const PostTaskInputSchema = z.object({
|
|
|
535
538
|
.optional(),
|
|
536
539
|
callback_secret: z.string().min(16).max(128).optional(),
|
|
537
540
|
idempotency_key: z.string().min(1).max(200).optional(),
|
|
541
|
+
}).refine((d) => (d.reward_usd !== undefined || d.max_budget_usd !== undefined) &&
|
|
542
|
+
!(d.reward_usd !== undefined && d.max_budget_usd !== undefined), {
|
|
543
|
+
message: "Provide either reward_usd (fixed price) or max_budget_usd (proposal mode), not both",
|
|
544
|
+
path: ["reward_usd"],
|
|
538
545
|
});
|
|
539
546
|
const GetTaskResultInputSchema = z.object({
|
|
540
547
|
task_id: z.string().min(1),
|
|
541
548
|
});
|
|
549
|
+
const SubmitReviewInputSchema = z.object({
|
|
550
|
+
task_id: z.string().min(1),
|
|
551
|
+
rating: z.number().int().min(1).max(10),
|
|
552
|
+
comment: z.string().min(1).max(1000).optional(),
|
|
553
|
+
});
|
|
554
|
+
const GetOperatorReviewsInputSchema = z.object({
|
|
555
|
+
operator_id: z.string().min(1),
|
|
556
|
+
});
|
|
557
|
+
const ListProposalsInputSchema = z.object({
|
|
558
|
+
task_id: z.string().min(1),
|
|
559
|
+
});
|
|
560
|
+
const AwardProposalToolInputSchema = z.object({
|
|
561
|
+
task_id: z.string().min(1),
|
|
562
|
+
proposal_id: z.string().min(1),
|
|
563
|
+
});
|
|
564
|
+
const RejectProposalToolInputSchema = z.object({
|
|
565
|
+
task_id: z.string().min(1),
|
|
566
|
+
proposal_id: z.string().min(1),
|
|
567
|
+
reason: z.string().max(200).optional(),
|
|
568
|
+
});
|
|
569
|
+
const CancelProposalWindowInputSchema = z.object({
|
|
570
|
+
task_id: z.string().min(1),
|
|
571
|
+
});
|
|
542
572
|
const FundAccountInputSchema = z.object({
|
|
543
573
|
amount_usd: z.number().min(MIN_DEPOSIT_USD).max(MAX_DEPOSIT_USD),
|
|
544
574
|
payment_method: z.enum(["usdc", "card", "bank_transfer"]).default("usdc"),
|
|
@@ -612,7 +642,7 @@ server.setRequestHandler(ListToolsRequestSchema, async () => ({
|
|
|
612
642
|
},
|
|
613
643
|
{
|
|
614
644
|
name: "post_task",
|
|
615
|
-
description: "Create a new task for a human operator. Supports physical tasks (VERIFICATION, PHOTO, DELIVERY, INSPECTION), digital tasks (CAPTCHA_SOLVING, FORM_FILLING, etc.), and credential tasks (ACCOUNT_CREATION, API_KEY_PROCUREMENT, etc.). For digital tasks prefer dispatch_digital_task; for credential tasks prefer dispatch_credential_task.
|
|
645
|
+
description: "Create a new task for a human operator. Supports physical tasks (VERIFICATION, PHOTO, DELIVERY, INSPECTION), digital tasks (CAPTCHA_SOLVING, FORM_FILLING, etc.), and credential tasks (ACCOUNT_CREATION, API_KEY_PROCUREMENT, etc.). For digital tasks prefer dispatch_digital_task; for credential tasks prefer dispatch_credential_task. Provide either reward_usd (fixed price; escrowed at creation) OR max_budget_usd (proposal mode; escrow created when you award a proposal).",
|
|
616
646
|
inputSchema: {
|
|
617
647
|
type: "object",
|
|
618
648
|
properties: {
|
|
@@ -623,7 +653,14 @@ server.setRequestHandler(ListToolsRequestSchema, async () => ({
|
|
|
623
653
|
properties: { lat: { type: "number" }, lng: { type: "number" }, address: { type: "string" } },
|
|
624
654
|
required: ["lat", "lng", "address"],
|
|
625
655
|
},
|
|
626
|
-
|
|
656
|
+
urgency: {
|
|
657
|
+
type: "string",
|
|
658
|
+
enum: ["standard", "priority", "urgent"],
|
|
659
|
+
description: "Urgency level (standard=24h pickup, priority=4h pickup, urgent=1h pickup + 4h completion SLA).",
|
|
660
|
+
},
|
|
661
|
+
reward_usd: { type: "number", description: "Fixed-price mode: reward in USD" },
|
|
662
|
+
max_budget_usd: { type: "number", description: "Proposal mode: maximum budget in USD (alternative to reward_usd)" },
|
|
663
|
+
proposal_deadline_minutes: { type: "number", description: "Proposal window length in minutes (default: 120)" },
|
|
627
664
|
deadline: { type: "string", description: "ISO 8601 deadline for task completion" },
|
|
628
665
|
proof_requirements: { type: "array", items: { type: "string" } },
|
|
629
666
|
task_type: {
|
|
@@ -634,7 +671,7 @@ server.setRequestHandler(ListToolsRequestSchema, async () => ({
|
|
|
634
671
|
callback_secret: { type: "string", description: "Optional secret to sign webhook callbacks" },
|
|
635
672
|
idempotency_key: { type: "string", description: "Optional key to make task creation safe to retry" },
|
|
636
673
|
},
|
|
637
|
-
required: ["title", "description", "location", "
|
|
674
|
+
required: ["title", "description", "location", "deadline", "proof_requirements", "task_type"],
|
|
638
675
|
},
|
|
639
676
|
},
|
|
640
677
|
{
|
|
@@ -738,6 +775,30 @@ server.setRequestHandler(ListToolsRequestSchema, async () => ({
|
|
|
738
775
|
required: ["task_id"],
|
|
739
776
|
},
|
|
740
777
|
},
|
|
778
|
+
{
|
|
779
|
+
name: "submit_review",
|
|
780
|
+
description: "Submit a 1-10 rating (and optional comment) for the operator on a COMPLETED task. One review per task. Comments are screened for safety.",
|
|
781
|
+
inputSchema: {
|
|
782
|
+
type: "object",
|
|
783
|
+
properties: {
|
|
784
|
+
task_id: { type: "string", description: "The completed task ID" },
|
|
785
|
+
rating: { type: "number", description: "Integer rating 1-10" },
|
|
786
|
+
comment: { type: "string", description: "Optional comment (max 1000 chars)" },
|
|
787
|
+
},
|
|
788
|
+
required: ["task_id", "rating"],
|
|
789
|
+
},
|
|
790
|
+
},
|
|
791
|
+
{
|
|
792
|
+
name: "get_operator_reviews",
|
|
793
|
+
description: "Get an operator's approved reviews and aggregate rating (agent-facing). Useful for building trust signals and choosing operators.",
|
|
794
|
+
inputSchema: {
|
|
795
|
+
type: "object",
|
|
796
|
+
properties: {
|
|
797
|
+
operator_id: { type: "string", description: "Operator ID" },
|
|
798
|
+
},
|
|
799
|
+
required: ["operator_id"],
|
|
800
|
+
},
|
|
801
|
+
},
|
|
741
802
|
{
|
|
742
803
|
name: "register_agent",
|
|
743
804
|
description: "Register a new HumanOps agent account. Returns an API key for authentication. You start in SANDBOX tier (tasks auto-complete with simulated operators). Verify your email to upgrade to VERIFIED tier.",
|
|
@@ -845,6 +906,49 @@ server.setRequestHandler(ListToolsRequestSchema, async () => ({
|
|
|
845
906
|
required: ["task_id"],
|
|
846
907
|
},
|
|
847
908
|
},
|
|
909
|
+
{
|
|
910
|
+
name: "list_proposals",
|
|
911
|
+
description: "List proposals for a proposal-mode task. Use this after creating a task with max_budget_usd.",
|
|
912
|
+
inputSchema: {
|
|
913
|
+
type: "object",
|
|
914
|
+
properties: { task_id: { type: "string", description: "The task ID" } },
|
|
915
|
+
required: ["task_id"],
|
|
916
|
+
},
|
|
917
|
+
},
|
|
918
|
+
{
|
|
919
|
+
name: "award_proposal",
|
|
920
|
+
description: "Award a proposal for a proposal-mode task. This creates escrow at award time and assigns the operator.",
|
|
921
|
+
inputSchema: {
|
|
922
|
+
type: "object",
|
|
923
|
+
properties: {
|
|
924
|
+
task_id: { type: "string", description: "The task ID" },
|
|
925
|
+
proposal_id: { type: "string", description: "The proposal ID to award" },
|
|
926
|
+
},
|
|
927
|
+
required: ["task_id", "proposal_id"],
|
|
928
|
+
},
|
|
929
|
+
},
|
|
930
|
+
{
|
|
931
|
+
name: "reject_proposal",
|
|
932
|
+
description: "Reject a proposal for a proposal-mode task (optional reason).",
|
|
933
|
+
inputSchema: {
|
|
934
|
+
type: "object",
|
|
935
|
+
properties: {
|
|
936
|
+
task_id: { type: "string", description: "The task ID" },
|
|
937
|
+
proposal_id: { type: "string", description: "The proposal ID to reject" },
|
|
938
|
+
reason: { type: "string", description: "Optional rejection reason" },
|
|
939
|
+
},
|
|
940
|
+
required: ["task_id", "proposal_id"],
|
|
941
|
+
},
|
|
942
|
+
},
|
|
943
|
+
{
|
|
944
|
+
name: "cancel_proposal_window",
|
|
945
|
+
description: "Close the proposal window by cancelling the task. This is useful when you no longer want proposals for a task in proposal mode.",
|
|
946
|
+
inputSchema: {
|
|
947
|
+
type: "object",
|
|
948
|
+
properties: { task_id: { type: "string", description: "The task ID to cancel" } },
|
|
949
|
+
required: ["task_id"],
|
|
950
|
+
},
|
|
951
|
+
},
|
|
848
952
|
{
|
|
849
953
|
name: "approve_estimate",
|
|
850
954
|
description: "Approve an operator's time estimate for a task. The operator will be notified and can start working. Only works when task status is ESTIMATE_PENDING.",
|
|
@@ -1038,6 +1142,34 @@ server.setRequestHandler(CallToolRequestSchema, async (request) => {
|
|
|
1038
1142
|
};
|
|
1039
1143
|
return { content: [{ type: "text", text: JSON.stringify(focused, null, 2) }] };
|
|
1040
1144
|
}
|
|
1145
|
+
case "submit_review": {
|
|
1146
|
+
const parsed = SubmitReviewInputSchema.safeParse(args);
|
|
1147
|
+
if (!parsed.success) {
|
|
1148
|
+
return {
|
|
1149
|
+
content: [{ type: "text", text: `Error: invalid input: ${parsed.error.message}` }],
|
|
1150
|
+
isError: true,
|
|
1151
|
+
};
|
|
1152
|
+
}
|
|
1153
|
+
const { task_id, rating, comment } = parsed.data;
|
|
1154
|
+
const result = await apiRequest(`/api/v1/tasks/${encodeURIComponent(task_id)}/review`, {
|
|
1155
|
+
method: "POST",
|
|
1156
|
+
body: JSON.stringify({ rating, ...(comment ? { comment } : {}) }),
|
|
1157
|
+
});
|
|
1158
|
+
return { content: [{ type: "text", text: JSON.stringify(result, null, 2) }] };
|
|
1159
|
+
}
|
|
1160
|
+
case "get_operator_reviews": {
|
|
1161
|
+
const parsed = GetOperatorReviewsInputSchema.safeParse(args);
|
|
1162
|
+
if (!parsed.success) {
|
|
1163
|
+
return {
|
|
1164
|
+
content: [{ type: "text", text: `Error: invalid input: ${parsed.error.message}` }],
|
|
1165
|
+
isError: true,
|
|
1166
|
+
};
|
|
1167
|
+
}
|
|
1168
|
+
const result = await apiRequest(`/api/v1/operators/${encodeURIComponent(parsed.data.operator_id)}/reviews`, {
|
|
1169
|
+
method: "GET",
|
|
1170
|
+
});
|
|
1171
|
+
return { content: [{ type: "text", text: JSON.stringify(result, null, 2) }] };
|
|
1172
|
+
}
|
|
1041
1173
|
case "get_deposit_address": {
|
|
1042
1174
|
const result = await apiRequest("/api/v1/agents/deposit-address", {
|
|
1043
1175
|
method: "GET",
|
|
@@ -1228,6 +1360,61 @@ server.setRequestHandler(CallToolRequestSchema, async (request) => {
|
|
|
1228
1360
|
});
|
|
1229
1361
|
return { content: [{ type: "text", text: JSON.stringify(result, null, 2) }] };
|
|
1230
1362
|
}
|
|
1363
|
+
case "list_proposals": {
|
|
1364
|
+
const parsed = ListProposalsInputSchema.safeParse(args);
|
|
1365
|
+
if (!parsed.success) {
|
|
1366
|
+
return {
|
|
1367
|
+
content: [{ type: "text", text: `Error: invalid input: ${parsed.error.message}` }],
|
|
1368
|
+
isError: true,
|
|
1369
|
+
};
|
|
1370
|
+
}
|
|
1371
|
+
const data = await apiRequest(`/api/v1/tasks/${encodeURIComponent(parsed.data.task_id)}/proposals`, {
|
|
1372
|
+
method: "GET",
|
|
1373
|
+
});
|
|
1374
|
+
return { content: [{ type: "text", text: JSON.stringify(data, null, 2) }] };
|
|
1375
|
+
}
|
|
1376
|
+
case "award_proposal": {
|
|
1377
|
+
const parsed = AwardProposalToolInputSchema.safeParse(args);
|
|
1378
|
+
if (!parsed.success) {
|
|
1379
|
+
return {
|
|
1380
|
+
content: [{ type: "text", text: `Error: invalid input: ${parsed.error.message}` }],
|
|
1381
|
+
isError: true,
|
|
1382
|
+
};
|
|
1383
|
+
}
|
|
1384
|
+
const result = await apiRequest(`/api/v1/tasks/${encodeURIComponent(parsed.data.task_id)}/award-proposal`, {
|
|
1385
|
+
method: "POST",
|
|
1386
|
+
body: JSON.stringify({ proposal_id: parsed.data.proposal_id }),
|
|
1387
|
+
});
|
|
1388
|
+
return { content: [{ type: "text", text: JSON.stringify(result, null, 2) }] };
|
|
1389
|
+
}
|
|
1390
|
+
case "reject_proposal": {
|
|
1391
|
+
const parsed = RejectProposalToolInputSchema.safeParse(args);
|
|
1392
|
+
if (!parsed.success) {
|
|
1393
|
+
return {
|
|
1394
|
+
content: [{ type: "text", text: `Error: invalid input: ${parsed.error.message}` }],
|
|
1395
|
+
isError: true,
|
|
1396
|
+
};
|
|
1397
|
+
}
|
|
1398
|
+
const body = parsed.data.reason ? { reason: parsed.data.reason } : {};
|
|
1399
|
+
const result = await apiRequest(`/api/v1/tasks/${encodeURIComponent(parsed.data.task_id)}/proposals/${encodeURIComponent(parsed.data.proposal_id)}/reject`, {
|
|
1400
|
+
method: "POST",
|
|
1401
|
+
body: JSON.stringify(body),
|
|
1402
|
+
});
|
|
1403
|
+
return { content: [{ type: "text", text: JSON.stringify(result, null, 2) }] };
|
|
1404
|
+
}
|
|
1405
|
+
case "cancel_proposal_window": {
|
|
1406
|
+
const parsed = CancelProposalWindowInputSchema.safeParse(args);
|
|
1407
|
+
if (!parsed.success) {
|
|
1408
|
+
return {
|
|
1409
|
+
content: [{ type: "text", text: `Error: invalid input: ${parsed.error.message}` }],
|
|
1410
|
+
isError: true,
|
|
1411
|
+
};
|
|
1412
|
+
}
|
|
1413
|
+
const result = await apiRequest(`/api/v1/tasks/${encodeURIComponent(parsed.data.task_id)}/cancel`, {
|
|
1414
|
+
method: "POST",
|
|
1415
|
+
});
|
|
1416
|
+
return { content: [{ type: "text", text: JSON.stringify(result, null, 2) }] };
|
|
1417
|
+
}
|
|
1231
1418
|
case "approve_estimate": {
|
|
1232
1419
|
const parsed = GetTaskResultInputSchema.safeParse(args);
|
|
1233
1420
|
if (!parsed.success) {
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@humanops/mcp-server",
|
|
3
|
-
"version": "0.3.
|
|
3
|
+
"version": "0.3.3",
|
|
4
4
|
"mcpName": "io.github.thepianistdirector/humanops",
|
|
5
5
|
"description": "MCP server for AI agents to dispatch real-world tasks to verified human operators via HumanOps",
|
|
6
6
|
"type": "module",
|