Package Exports
This package does not declare an exports field, so the exports above have been automatically detected and optimized by JSPM instead. If any package subpath is missing, it is recommended to post an issue to the original package (askexperts) to support the "exports" field. If that is not possible, create a JSPM override to customize the exports field for this package.
Readme
AskExperts MCP Server
An MCP server that allows users to find experts on a subject, ask them questions, pay them for their answers, and curate the experts.
Features
- Find experts on a subject by posting a public summary of your question
- Experts can bid on answering your question
- Pay experts for their answers
- Manage list of expert scores
Installation
Local Development
# Clone the repository
git clone <repository-url>
cd askexperts
# Install dependencies
npm installUsing NPX
You can run the MCP server directly using npx without installing it:
npx -y askexpertsUsage
Starting the Server
Local Development
# Run the MCP server
npm run mcp
# Development mode with auto-reload
npm run dev
# Build and start in production mode
npm run build
npm startUsing NPX
# Run directly without installation
npx -y askexperts
# Or install globally and run
npm install -g askexperts
askexpertsUsing the MCP Server
The server exposes the following MCP tools:
find_experts
Find experts on a subject by posting an anonymous publicly visible summary of your question. It should omit all private details and personally identifiable information, be short, concise and include relevant tags. Returns a list of bids by experts who are willing to answer your question and their invoices for payments.
Parameters:
public_question_summary(string, required): A public summary of the question, omitting private details and PIItags(string[], optional): List of tags for discovery (required if expert_pubkeys not set)expert_pubkeys(string[], optional): List of expert public keys to direct the question to, if those were already discoveredmax_bid_sats(number, optional): Maximum payment amount willing to pay for an answer, in Bitcoin satoshis
Returns: A JSON string containing:
bids: Array of bid objects, each containing:message_id(string): Bid payload event IDpubkey(string): Expert's public keybid_sats(number): Amount of the bid in satoshisoffer(string): Expert's offer description
id(string): ID of the ask event
ask_experts
After you receive bids from experts, select good ones and you can send the question to these experts. For each bid, information received from find_experts tool must be included, you can pay invoices yourself and provide preimages, or leave preimages empty and we pay from built-in wallet. Relays and invoices are stored internally and clients don't have to pass them from bids to questions.
Note: If the server does not have NWC_CONNECTION_STRING set, you must pay invoices yourself and provide the preimages when calling this tool.
Parameters:
ask_id(string, required): Id of the ask, received from find_experts.question(string, required): The detailed question to send to experts, might include more sensitive data as the questions are encrypted.experts(array, required): Array of experts to send questions to, each containing:message_id(string, required): Bid payload event ID for the first question, or last answer event ID for a followuppubkey(string, required): Expert's public keypreimage(string, conditional): Payment preimage for verification (required if NWC_CONNECTION_STRING not set)bid_sats(number, conditional): Amount of the bid in satoshis (required when preimage is not provided, must match the invoice amount)
timeout(number, optional): Timeout in milliseconds for sending the questions and receiving the answers (default: 5000ms)
Returns: A JSON string containing:
total(number): Total number of question resultssent(number): Number of questions successfully sentfailed(number): Number of questions that failed to sendfailed_payments(number): Number of questions that failed to get paidreceived(number): Number of answers receivedtimeout(number): Number of answers that timed outinsufficient_balance(boolean): True if internal wallet is out of funds (only relevant whenNWC_CONNECTION_STRINGis set)results(array): Detailed results for each expert question/answer, each containing:message_id(string): Message ID that was provided as inputexpert_pubkey(string): Expert's public keypayment_hash(string, optional): Payment hash of the bid, useful to find the payment in client's walletstatus(string): Status of the question/answer process ('sent', 'failed', 'received', 'timeout')content(string, optional): Content of the answer if receivedfollowup_sats(number, optional): If followup is allowed by expert, includes the amount of sats to pay for a followup questionfollowup_message_id(string, optional): ID of the message to ask a followup question, to be passed to ask_expertsfollowup_invoice(string, optional): Lightning invoice for followup question if available (only included whenNWC_CONNECTION_STRINGis not set)error(string, optional): Error message if failed
Example Usage with MCP Client
Using with Local Server
import { McpClient } from "@modelcontextprotocol/sdk/client/mcp.js";
import { StdioClientTransport } from "@modelcontextprotocol/sdk/client/stdio.js";
// Create an MCP client
const client = new McpClient();
// Connect to the server using stdio transport
const transport = new StdioClientTransport();
await client.connect(transport);
// Call the find_experts tool
const findResult = await client.callTool("find_experts", {
public_question_summary: "How to implement a blockchain in JavaScript?",
tags: ["blockchain", "javascript", "programming"],
// expert_pubkeys: ["pubkey1", "pubkey2"], // Optional: direct the question to specific experts
max_bid_sats: 2000
});
// Get the bids and ask ID from the result
const { bids, id } = JSON.parse(findResult);
// Select bids to send questions to
const selectedBids = bids.slice(0, 2); // Select first two bids
// Call the ask_experts tool with selected experts
const askResult = await client.callTool("ask_experts", {
ask_id: id,
question: "I need a detailed explanation of how to implement a simple blockchain in JavaScript with examples.",
experts: selectedBids.map(bid => ({
message_id: bid.message_id,
pubkey: bid.pubkey,
bid_sats: bid.bid_sats // Required to match the invoice amount
// preimage is not provided, so the server will pay using NWC_CONNECTION_STRING
})),
timeout: 10000 // Wait 10 seconds for answers
});
console.log(askResult);Using with NPX
You can use the MCP server with a client by spawning it as a child process:
import { McpClient } from "@modelcontextprotocol/sdk/client/mcp.js";
import { ChildProcessClientTransport } from "@modelcontextprotocol/sdk/client/child-process.js";
import { spawn } from "child_process";
// Create an MCP client
const client = new McpClient();
// Spawn the MCP server as a child process using npx
const serverProcess = spawn("npx", ["-y", "askexperts"]);
// Connect to the server using child process transport
const transport = new ChildProcessClientTransport(serverProcess);
await client.connect(transport);
// Call the find_experts tool
const findResult = await client.callTool("find_experts", {
public_question_summary: "How to implement a blockchain in JavaScript?",
tags: ["blockchain", "javascript", "programming"],
// expert_pubkeys: ["pubkey1", "pubkey2"], // Optional: direct the question to specific experts
max_bid_sats: 2000
});
// Get the bids and ask ID from the result
const { bids, id } = JSON.parse(findResult);
// Select bids to send questions to
const selectedBids = bids.slice(0, 2); // Select first two bids
// Call the ask_experts tool with selected experts
const askResult = await client.callTool("ask_experts", {
ask_id: id,
question: "I need a detailed explanation of how to implement a simple blockchain in JavaScript with examples.",
experts: selectedBids.map(bid => ({
message_id: bid.message_id,
pubkey: bid.pubkey,
bid_sats: bid.bid_sats, // Required to match the invoice amount
// preimage is not provided, so the server will pay using NWC_CONNECTION_STRING
})),
timeout: 10000 // Wait 10 seconds for answers
});
console.log(askResult);Environment Variables
NWC_CONNECTION_STRING
The NWC_CONNECTION_STRING environment variable enables the built-in wallet functionality in the ask_experts tool. When set, it allows the MCP server to automatically pay Lightning invoices for expert bids without requiring the client to provide payment preimages.
What is NWC?
NWC (Nostr Wallet Connect) is a protocol that allows applications to connect to a Lightning wallet. The connection string is a URL that contains the necessary information to connect to a wallet that supports the NWC protocol.
Setting up NWC_CONNECTION_STRING
To enable the built-in wallet:
- Obtain a NWC connection string from a compatible wallet (like Alby)
- Set the environment variable before starting the server:
# Set the environment variable
export NWC_CONNECTION_STRING="nostr+walletconnect://..."
# Then start the server
npm run mcpHow it works
When a client calls the ask_experts tool with bids that include invoices but no preimages:
- The server checks if
NWC_CONNECTION_STRINGis set - If set, it uses the NWC client to pay the invoices automatically
- It obtains payment preimages from successful payments
- These preimages are used to authenticate the questions sent to experts
Without this environment variable, clients must pay invoices themselves and provide the preimages when calling the ask_experts tool.
Example with built-in wallet
// With NWC_CONNECTION_STRING set on the server, clients can simply provide bid information
const askResult = await client.callTool("ask_experts", {
ask_id: findResult.structuredContent.id,
question: "My detailed question here...",
experts: selectedBids.map(bid => ({
message_id: bid.message_id,
pubkey: bid.pubkey,
bid_sats: bid.bid_sats // Required to match the invoice amount
// No preimage needed - server will pay using the built-in wallet
}))
});License
MIT