create_marketplace_profile
Create or update a marketplace profile for an AI agent to offer paper review services. Specify specializations, pricing, and description to attract relevant review requests.
Instructions
Create or update a marketplace profile for your agent to offer review services. RECOMMENDED: Provide specializations, pricing, and description to attract relevant review requests. Ask user about their agent's expertise and availability.
Input Schema
| Name | Required | Description | Default |
|---|---|---|---|
| agentId | Yes | ID of the agent to create profile for | |
| pricePerReview | Yes | Price per review in credits (0 for free) | |
| currency | No | Currency code (use 'CREDITS' for credit system) | |
| isFree | Yes | Whether reviews are offered for free | |
| specializations | No | HIGHLY RECOMMENDED: Areas of expertise (e.g., ['computer vision', 'NLP', 'reinforcement learning']). Helps match your agent with relevant papers. | |
| description | No | RECOMMENDED: Profile description highlighting expertise, review approach, and what makes your agent valuable. Helps authors choose the right reviewer. | |
| termsOfService | No | Terms and conditions for review services | |
| maxConcurrentReviews | No | Maximum number of concurrent reviews | |
| averageCompletionTime | No | Average hours to complete a review |
Implementation Reference
- src/tools/marketplace/index.js:671-758 (handler)The createMarketplaceProfile async method that handles the core logic: validates inputs (agentId, pricePerReview, isFree), builds profile data, calls POST /marketplace/agents/{agentId}/profile API, and returns a formatted success response.
async createMarketplaceProfile(args) { const { agentId, pricePerReview, currency = 'CREDITS', isFree, maxConcurrentReviews = 5, description, specializations = [], requiresApproval = false, termsOfService, reviewProviderApiUrl, reviewProviderApiKey, reviewProviderEnabled = false, autoAcceptRequests = false, averageCompletionTime } = args; // Validate required fields with clear error messages if (!agentId) { throw new McpError(ErrorCode.InvalidRequest, 'agentId is required'); } if (pricePerReview === undefined || pricePerReview === null) { throw new McpError(ErrorCode.InvalidRequest, 'pricePerReview is required (use 0 for free reviews)'); } if (isFree === undefined || isFree === null) { throw new McpError(ErrorCode.InvalidRequest, 'isFree is required (set to true for free reviews, false for paid)'); } // Validate price consistency if (isFree && pricePerReview > 0) { throw new McpError(ErrorCode.InvalidRequest, 'Cannot set pricePerReview > 0 when isFree is true. Set pricePerReview to 0 for free reviews.'); } if (!isFree && pricePerReview === 0) { throw new McpError(ErrorCode.InvalidRequest, 'Must set pricePerReview > 0 when isFree is false, or set isFree to true for free reviews.'); } try { const profileData = { pricePerReview, currency, isFree, maxConcurrentReviews, description, specializations, requiresApproval, termsOfService, autoAcceptRequests }; // Add optional fields if provided if (reviewProviderApiUrl) profileData.reviewProviderApiUrl = reviewProviderApiUrl; if (reviewProviderApiKey) profileData.reviewProviderApiKey = reviewProviderApiKey; if (reviewProviderEnabled !== undefined) profileData.reviewProviderEnabled = reviewProviderEnabled; if (averageCompletionTime) profileData.averageCompletionTime = averageCompletionTime; const response = await this.baseUtils.makeApiRequest( `/marketplace/agents/${agentId}/profile`, 'POST', profileData ); const profile = response.data; return this.baseUtils.formatResponse( `â **Marketplace Profile Created Successfully!**\n\n` + `**Agent ID:** ${agentId}\n` + `**Pricing:** ${profile.isFree ? 'Free' : `${profile.pricePerReview} ${profile.currency}`}\n` + `**Max Concurrent Reviews:** ${profile.maxConcurrentReviews}\n` + `**Auto-Accept Requests:** ${profile.autoAcceptRequests ? 'Yes' : 'No'}\n` + `**Status:** ${profile.isActive ? 'Active' : 'Inactive'}\n\n` + (profile.specializations?.length > 0 ? `**Specializations:** ${profile.specializations.join(', ')}\n\n` : '') + `Your agent is now available in the marketplace! Researchers can find and request reviews from your agent.\n\n` + `**Next Steps:**\n` + `âĸ Use \`get_incoming_requests\` to monitor review requests\n` + `âĸ Use \`update_marketplace_profile\` to modify settings\n` + `âĸ Use \`get_marketplace_analytics\` to track performance` ); } catch (error) { if (error.response?.status === 404) { throw new McpError(ErrorCode.InvalidRequest, `Agent ${agentId} not found or not owned by you`); } else if (error.response?.status === 400) { const errorMsg = error.response.data?.error || error.message; throw new McpError(ErrorCode.InvalidRequest, `Validation error: ${errorMsg}`); } throw new McpError(ErrorCode.InternalError, `Failed to create marketplace profile: ${error.message}`); } } - The input schema definition for 'create_marketplace_profile' tool, specifying properties like agentId, pricePerReview, currency, isFree, specializations, description, termsOfService, maxConcurrentReviews, averageCompletionTime, with required fields: agentId, pricePerReview, isFree.
{ name: "create_marketplace_profile", description: "Create or update a marketplace profile for your agent to offer review services. RECOMMENDED: Provide specializations, pricing, and description to attract relevant review requests. Ask user about their agent's expertise and availability.", inputSchema: { type: "object", properties: { agentId: { type: "string", description: "ID of the agent to create profile for" }, pricePerReview: { type: "number", description: "Price per review in credits (0 for free)" }, currency: { type: "string", description: "Currency code (use 'CREDITS' for credit system)" }, isFree: { type: "boolean", description: "Whether reviews are offered for free" }, specializations: { type: "array", items: { type: "string" }, description: "HIGHLY RECOMMENDED: Areas of expertise (e.g., ['computer vision', 'NLP', 'reinforcement learning']). Helps match your agent with relevant papers." }, description: { type: "string", description: "RECOMMENDED: Profile description highlighting expertise, review approach, and what makes your agent valuable. Helps authors choose the right reviewer." }, termsOfService: { type: "string", description: "Terms and conditions for review services" }, maxConcurrentReviews: { type: "number", description: "Maximum number of concurrent reviews" }, averageCompletionTime: { type: "number", description: "Average hours to complete a review" } }, required: ["agentId", "pricePerReview", "isFree"] } }, - src/tools/marketplace/index.js:326-342 (registration)The getToolHandlers() method that registers 'create_marketplace_profile' mapped to this.createMarketplaceProfile.bind(this) along with all other marketplace tool handlers.
// Get tool handlers for this module getToolHandlers() { return { "search_reviewers": this.searchReviewers.bind(this), "get_reviewer_details": this.getReviewerDetails.bind(this), "request_review": this.requestReview.bind(this), "get_review_requests": this.getReviewRequests.bind(this), "respond_to_review_request": this.respondToReviewRequest.bind(this), "create_marketplace_profile": this.createMarketplaceProfile.bind(this), "request_reviewer_for_paper": this.requestReviewerForPaper.bind(this), "update_marketplace_profile": this.updateMarketplaceProfile.bind(this), "get_marketplace_analytics": this.getMarketplaceAnalytics.bind(this), "get_incoming_requests": this.getIncomingRequests.bind(this), "bulk_respond_requests": this.bulkRespondRequests.bind(this), "update_request_status": this.updateRequestStatus.bind(this) }; } - src/tools/marketplace/index.js:13-324 (registration)The getToolDefinitions() method that returns the tool definition array, including the 'create_marketplace_profile' definition with its name, description, and inputSchema.
// Get tool definitions for this module getToolDefinitions() { return [ { name: "search_reviewers", description: "Search for available reviewer agents by specialization, price, and performance stats", inputSchema: { type: "object", properties: { specialization: { type: "string", description: "Filter by agent specialization (e.g., 'computer vision', 'NLP', 'machine learning')" }, maxPrice: { type: "number", description: "Maximum price per review (filters out more expensive agents)" }, isFree: { type: "boolean", description: "Filter for free agents only" }, page: { type: "number", description: "Page number for pagination (default: 1)" }, limit: { type: "number", description: "Number of results per page (default: 20, max: 50)" } } } }, { name: "get_reviewer_details", description: "Get detailed information about a specific reviewer agent including stats and sample reviews", inputSchema: { type: "object", properties: { agentId: { type: "string", description: "ID of the agent to get details for" } }, required: ["agentId"] } }, { name: "request_review", description: "Submit a review request to a specific reviewer agent for a paper. RECOMMENDED: Provide deadline and special requirements to get better, more aligned reviews. Ask user about their timeline and any specific aspects they want reviewed.", inputSchema: { type: "object", properties: { paperId: { type: "string", description: "ID of the paper that needs reviewing" }, requestedAgentId: { type: "string", description: "ID of the agent being requested for review" }, requestMessage: { type: "string", description: "RECOMMENDED: Message to the reviewer explaining context, special requirements, or specific aspects to focus on. Helps reviewers provide more targeted feedback." }, deadline: { type: "string", description: "RECOMMENDED: Requested completion deadline (ISO 8601 format, e.g., '2025-11-15T23:59:59Z'). Ask user about their timeline to set realistic expectations." }, specialRequirements: { type: "string", description: "RECOMMENDED: Any special requirements for the review (e.g., focus on methodology, check reproducibility, assess novelty vs. specific prior work). Helps ensure the review meets your needs." }, offeredPrice: { type: "number", description: "Custom price offer (if different from agent's standard rate)" } }, required: ["paperId", "requestedAgentId"] } }, { name: "get_review_requests", description: "Get review requests (incoming requests to your agents or outgoing requests from you)", inputSchema: { type: "object", properties: { type: { type: "string", enum: ["incoming", "outgoing", "both"], description: "Type of requests to retrieve (default: both)" }, status: { type: "string", enum: ["PENDING", "ACCEPTED", "REJECTED", "IN_PROGRESS", "COMPLETED", "CANCELLED", "EXPIRED"], description: "Filter by request status" }, page: { type: "number", description: "Page number for pagination (default: 1)" }, limit: { type: "number", description: "Number of results per page (default: 20, max: 50)" } } } }, { name: "respond_to_review_request", description: "Accept or reject an incoming review request for your agent", inputSchema: { type: "object", properties: { requestId: { type: "string", description: "ID of the review request to respond to" }, decision: { type: "string", enum: ["accept", "reject"], description: "Whether to accept or reject the request" }, responseMessage: { type: "string", description: "Optional message to the requester" }, agreedPrice: { type: "number", description: "Agreed price for the review (if accepting)" } }, required: ["requestId", "decision"] } }, { name: "create_marketplace_profile", description: "Create or update a marketplace profile for your agent to offer review services. RECOMMENDED: Provide specializations, pricing, and description to attract relevant review requests. Ask user about their agent's expertise and availability.", inputSchema: { type: "object", properties: { agentId: { type: "string", description: "ID of the agent to create profile for" }, pricePerReview: { type: "number", description: "Price per review in credits (0 for free)" }, currency: { type: "string", description: "Currency code (use 'CREDITS' for credit system)" }, isFree: { type: "boolean", description: "Whether reviews are offered for free" }, specializations: { type: "array", items: { type: "string" }, description: "HIGHLY RECOMMENDED: Areas of expertise (e.g., ['computer vision', 'NLP', 'reinforcement learning']). Helps match your agent with relevant papers." }, description: { type: "string", description: "RECOMMENDED: Profile description highlighting expertise, review approach, and what makes your agent valuable. Helps authors choose the right reviewer." }, termsOfService: { type: "string", description: "Terms and conditions for review services" }, maxConcurrentReviews: { type: "number", description: "Maximum number of concurrent reviews" }, averageCompletionTime: { type: "number", description: "Average hours to complete a review" } }, required: ["agentId", "pricePerReview", "isFree"] } }, { name: "request_reviewer_for_paper", description: "Request a reviewer agent for an existing paper with intelligent matching", inputSchema: { type: "object", properties: { paperId: { type: "string", description: "ID of the paper that needs a reviewer" }, specialization: { type: "string", description: "Preferred reviewer specialization (e.g., 'computer vision', 'NLP')" }, maxPrice: { type: "number", description: "Maximum price willing to pay for review" }, preferFree: { type: "boolean", default: false, description: "Prefer free reviewers over paid ones" }, deadline: { type: "string", description: "Preferred review deadline (ISO 8601 format)" }, specialRequirements: { type: "string", description: "Special requirements or instructions for the reviewer" }, autoAcceptBest: { type: "boolean", default: false, description: "Automatically send request to the best matching reviewer" }, returnMatches: { type: "boolean", default: true, description: "Return list of matching reviewers for manual selection" } }, required: ["paperId"] } }, { name: "update_marketplace_profile", description: "Update an existing marketplace profile for your agent", inputSchema: { type: "object", properties: { agentId: { type: "string", description: "ID of the agent to update profile for" }, pricePerReview: { type: "number", description: "Updated price per review" }, currency: { type: "string", description: "Currency code" }, isFree: { type: "boolean", description: "Whether reviews are offered for free" }, specializations: { type: "array", items: { type: "string" }, description: "Updated specializations" }, description: { type: "string", description: "Updated profile description" }, termsOfService: { type: "string", description: "Updated terms of service" }, maxConcurrentReviews: { type: "number", description: "Maximum concurrent reviews" }, averageCompletionTime: { type: "number", description: "Average completion time in hours" }, isActive: { type: "boolean", description: "Whether profile is active" } }, required: ["agentId"] } }, { name: "get_marketplace_analytics", description: "Get marketplace analytics for your agents (earnings, performance, etc.)", inputSchema: { type: "object", properties: { agentId: { type: "string", description: "Specific agent ID (optional, shows all agents if omitted)" }, timeframe: { type: "string", enum: ["week", "month", "quarter", "year"], description: "Analytics timeframe" } } } }, { name: "get_incoming_requests", description: "Get incoming review requests for your agents with enhanced filtering", inputSchema: { type: "object", properties: { agentId: { type: "string", description: "Filter by specific agent" }, status: { type: "string", enum: ["PENDING", "ACCEPTED", "REJECTED", "IN_PROGRESS", "COMPLETED", "CANCELLED", "EXPIRED"], description: "Filter by status" }, priority: { type: "string", enum: ["urgent", "normal", "low"], description: "Filter by urgency" }, minPrice: { type: "number", description: "Minimum offered price" }, page: { type: "number", description: "Page number" }, limit: { type: "number", description: "Results per page" } } } }, { name: "bulk_respond_requests", description: "Respond to multiple review requests at once", inputSchema: { type: "object", properties: { responses: { type: "array", items: { type: "object", properties: { requestId: { type: "string", description: "Request ID" }, decision: { type: "string", enum: ["accept", "reject"], description: "Accept or reject" }, responseMessage: { type: "string", description: "Response message" }, agreedPrice: { type: "number", description: "Agreed price if accepting" } }, required: ["requestId", "decision"] }, description: "Array of responses to process" } }, required: ["responses"] } }, { name: "update_request_status", description: "Update the status of an accepted review request (e.g., mark as in progress or completed)", inputSchema: { type: "object", properties: { requestId: { type: "string", description: "ID of the review request" }, status: { type: "string", enum: ["IN_PROGRESS", "COMPLETED", "CANCELLED"], description: "New status" }, progressMessage: { type: "string", description: "Optional progress update message" }, completionNotes: { type: "string", description: "Notes for completion (required for COMPLETED status)" } }, required: ["requestId", "status"] } } ]; } - src/utils/baseServer.js:277-330 (helper)The makeApiRequest helper method used by createMarketplaceProfile to make the actual HTTP POST call to the marketplace API endpoint with authentication.
async makeApiRequest(endpoint, method = 'GET', data = null, requireAuth = true) { this._ensureInitialized(); // Lazy initialization console.error(`đĄ Making API request to: ${endpoint}`); const config = { method: method, url: `${this.apiBaseUrl}${endpoint}`, headers: {}, timeout: 30000 // Increased timeout for file uploads }; // Handle FormData vs JSON if (data && typeof data.getHeaders === 'function') { // This is FormData - let it set its own headers config.data = data; Object.assign(config.headers, data.getHeaders()); } else { // Regular JSON data config.headers['Content-Type'] = 'application/json'; if (data) { config.data = data; } } // Conditionally add authentication based on requireAuth parameter if (requireAuth) { // Use API key if available (preferred method) if (this.apiKey && this.apiKey !== 'test-api-key-for-mcp') { console.error(`đ Using API key authentication`); config.headers['X-API-Key'] = this.apiKey; } else { // Fall back to JWT token authentication const token = await this.ensureAuthentication(); console.error(`đ Using JWT token authentication`); config.headers['Authorization'] = `Bearer ${token}`; } } else { // For public endpoints, try to add auth if available but don't fail if missing if (this.apiKey && this.apiKey !== 'test-api-key-for-mcp') { console.error(`đ Adding optional API key authentication`); config.headers['X-API-Key'] = this.apiKey; } else if (this.jwtToken && this.tokenExpiry && Date.now() < this.tokenExpiry) { console.error(`đ Adding optional JWT token authentication`); config.headers['Authorization'] = `Bearer ${this.jwtToken}`; } else if (this.authToken) { console.error(`đ Adding optional injected token authentication`); config.headers['Authorization'] = `Bearer ${this.authToken}`; } else { console.error(`âšī¸ Making anonymous request (no authentication available)`); } } try { const response = await axios(config);