Strip em-dashes from tool descriptions

This commit is contained in:
Qian
2026-07-18 05:43:43 +00:00
parent 56cf12945d
commit e77103ea61
3 changed files with 9 additions and 9 deletions
+1 -1
View File
@@ -39,7 +39,7 @@ Omit `QIAN_KEY` for read-only mode (market data still works). Use a dedicated ho
## Tokenized stocks ## Tokenized stocks
Robinhood Chain carries tokenized stocks (NVDA, TSLA, SPY, and more) issued by a third party (Robinhood Assets); Qian is a non-custodial venue, not the issuer. US persons are restricted from trading them — the read tools (`list_stocks`, `quote_stock`) work for everyone, but `buy_stock` and `sell_stock` are for non-US persons only. The server is headless and cannot verify location, so that restriction is on you to honor. Robinhood Chain carries tokenized stocks (NVDA, TSLA, SPY, and more) issued by a third party (Robinhood Assets); Qian is a non-custodial venue, not the issuer. US persons are restricted from trading them. The read tools (`list_stocks`, `quote_stock`) work for everyone, but `buy_stock` and `sell_stock` are for non-US persons only. The server is headless and cannot verify location, so that restriction is on you to honor.
## Configuration ## Configuration
+1 -1
View File
@@ -1,6 +1,6 @@
{ {
"name": "@qianexchange/mcp", "name": "@qianexchange/mcp",
"version": "0.1.4", "version": "0.1.5",
"description": "MCP server for the Qian multichain DEX & launchpad (qian.ag) — launch and trade tokens from any MCP-capable agent", "description": "MCP server for the Qian multichain DEX & launchpad (qian.ag) — launch and trade tokens from any MCP-capable agent",
"type": "module", "type": "module",
"bin": { "qian-mcp": "server.js" }, "bin": { "qian-mcp": "server.js" },
+7 -7
View File
@@ -97,7 +97,7 @@ const RWA_CATALOG = [
{ symbol: 'SLV', name: 'Silver ETF', address: '0x411eFb0E7f985935DAec3D4C3ebaEa0d0AD7D89f', soon: true }, { symbol: 'SLV', name: 'Silver ETF', address: '0x411eFb0E7f985935DAec3D4C3ebaEa0d0AD7D89f', soon: true },
] ]
// Advisory surfaced on the trade tools; the server is headless and can't gate by location. // Advisory surfaced on the trade tools; the server is headless and can't gate by location.
const RWA_RESTRICTED = 'US persons are restricted from trading tokenized stocks (they are securities). This tool cannot verify location — calling buy_stock/sell_stock confirms you are not a US person and not trading from the US. US users may view and quote only. Tokens are issued by a third party (Robinhood Assets); Qian is a non-custodial venue, not the issuer.' const RWA_RESTRICTED = 'US persons are restricted from trading tokenized stocks (they are securities). This tool cannot verify location. Calling buy_stock/sell_stock confirms you are not a US person and not trading from the US. US users may view and quote only. Tokens are issued by a third party (Robinhood Assets); Qian is a non-custodial venue, not the issuer.'
function resolveStock(q) { function resolveStock(q) {
const isAddr = /^0x[0-9a-fA-F]{40}$/.test(q) const isAddr = /^0x[0-9a-fA-F]{40}$/.test(q)
@@ -261,7 +261,7 @@ server.registerTool('my_positions', {
}) })
server.registerTool('quote_buy', { server.registerTool('quote_buy', {
description: 'Preview buying a token with ETH via QianSwapRouter (1% router fee included). Read-only — no wallet or key needed. Returns expected tokens out.', description: 'Preview buying a token with ETH via QianSwapRouter (1% router fee included). Read-only, no wallet or key needed. Returns expected tokens out.',
inputSchema: { chain: chainSlug, address, eth_amount: z.string().describe('ETH to spend, e.g. "0.05"') }, inputSchema: { chain: chainSlug, address, eth_amount: z.string().describe('ETH to spend, e.g. "0.05"') },
}, async ({ chain, address: addr, eth_amount }) => { }, async ({ chain, address: addr, eth_amount }) => {
const out = await quoteOut(chain, addr, 'buy', ethers.parseEther(eth_amount)) const out = await quoteOut(chain, addr, 'buy', ethers.parseEther(eth_amount))
@@ -269,7 +269,7 @@ server.registerTool('quote_buy', {
}) })
server.registerTool('quote_sell', { server.registerTool('quote_sell', {
description: 'Preview selling a token for ETH via QianSwapRouter (1% router fee included). Read-only — no wallet, key, or approval needed. Returns expected ETH out.', description: 'Preview selling a token for ETH via QianSwapRouter (1% router fee included). Read-only. No wallet, key, or approval needed. Returns expected ETH out.',
inputSchema: { chain: chainSlug, address, token_amount: z.string().describe('Tokens to sell in whole tokens, e.g. "1000000"') }, inputSchema: { chain: chainSlug, address, token_amount: z.string().describe('Tokens to sell in whole tokens, e.g. "1000000"') },
}, async ({ chain, address: addr, token_amount }) => { }, async ({ chain, address: addr, token_amount }) => {
let out let out
@@ -331,9 +331,9 @@ server.registerTool('sell', {
server.registerTool('launch_token', { server.registerTool('launch_token', {
description: [ description: [
'Launch a new token on Qian: 1B supply, full supply as locked one-sided liquidity (LP owned forever by QianLocker — no rug possible), fees stream to you as creator (70%) and the platform (30%).', 'Launch a new token on Qian: 1B supply, full supply as locked one-sided liquidity (LP owned forever by QianLocker, no rug possible), fees stream to you as creator (70%) and the platform (30%).',
'Costs the deploy fee (~0.0005 ETH) + optional dev_buy_eth. Tiers set starting FDV: 1=1 ETH, 2=2, 3=5, 4=10.', 'Costs the deploy fee (~0.0005 ETH) + optional dev_buy_eth. Tiers set starting FDV: 1=1 ETH, 2=2, 3=5, 4=10.',
'creator_fee_pct is the trading tax (0.5%–20%) you earn on every swap — it is the V4 pool fee, immutable once launched. There are no anti-snipe / dead-window / max-wallet options in V2.', 'creator_fee_pct is the trading tax (0.5%–20%) you earn on every swap. It is the V4 pool fee, immutable once launched. There are no anti-snipe / dead-window / max-wallet options in V2.',
].join(' '), ].join(' '),
inputSchema: { inputSchema: {
chain: chainSlug, chain: chainSlug,
@@ -393,7 +393,7 @@ server.registerTool('pending_fees', {
}) })
server.registerTool('collect_fees', { server.registerTool('collect_fees', {
description: 'Collect accrued trading fees for a token via QianFeeRouter (permissionless — anyone can trigger; payout always goes 70% to the token creator, 30% to the platform).', description: 'Collect accrued trading fees for a token via QianFeeRouter (permissionless, anyone can trigger; payout always goes 70% to the token creator, 30% to the platform).',
inputSchema: { chain: chainSlug, address }, inputSchema: { chain: chainSlug, address },
}, async ({ chain, address: addr }) => { }, async ({ chain, address: addr }) => {
const feeRouter = new ethers.Contract(CHAINS[chain].feeRouter, FEE_ROUTER_ABI, wallet(chain)) const feeRouter = new ethers.Contract(CHAINS[chain].feeRouter, FEE_ROUTER_ABI, wallet(chain))
@@ -418,7 +418,7 @@ server.registerTool('list_stocks', {
})) }))
server.registerTool('quote_stock', { server.registerTool('quote_stock', {
description: 'Preview a tokenized-stock trade (Robinhood Chain, 1% router fee included). Read-only — no wallet or key needed. buy: amount is ETH to spend; sell: amount is tokens to sell.', description: 'Preview a tokenized-stock trade (Robinhood Chain, 1% router fee included). Read-only, no wallet or key needed. buy: amount is ETH to spend; sell: amount is tokens to sell.',
inputSchema: { stock: stockArg, side: z.enum(['buy', 'sell']), amount: z.string().describe('ETH for buy, tokens for sell, e.g. "0.1"') }, inputSchema: { stock: stockArg, side: z.enum(['buy', 'sell']), amount: z.string().describe('ETH for buy, tokens for sell, e.g. "0.1"') },
}, async ({ stock, side, amount }) => { }, async ({ stock, side, amount }) => {
const s = resolveStock(stock) const s = resolveStock(stock)