值得收藏!一文掌握MCP智能投资顾问:征询与采样机制实战全解析(TaoToken 统一 Key 接入版)

发布时间:2026/10/9 17:31:01
值得收藏!一文掌握MCP智能投资顾问:征询与采样机制实战全解析(TaoToken 统一 Key 接入版)
1. 从排队两小时到秒级响应MCP 智能投资顾问要解决的真实问题传统投资咨询的体验很多人应该都有印象去银行网点排号等半小时起步见到顾问聊二十分钟拿到的建议还未必贴合自己的实际情况。更麻烦的是人工顾问的服务时间有限晚上想咨询只能等第二天。而 MCP 智能投资顾问这套方案核心就是用 LLM 的推理能力加上 MCP 协议的征询与采样机制把「收集用户信息 → 调用模型生成建议 → 格式化返回」这条链路自动化跑通。MCPModel Context Protocol在这里扮演的角色是连接 LLM 与外部工具、数据、用户交互的桥梁。它让 LLM 不再只是一个「你问我答」的聊天框而是能主动发起征询Elicitation向用户收集结构化信息再通过采样Sampling把整理好的上下文交给模型生成决策建议。适合谁适合想用 FastMCP 快速搭建投顾类工具链的开发者也适合对 MCP 征询与采样机制感兴趣、想找一个完整可跑通案例的技术同学。我试过把这套流程从零搭起来踩过的坑主要集中在征询 handler 的返回值类型和采样 handler 的消息格式上。下面把可复制的配置、代码和验证步骤完整拆开讲你跟着操作就能在本地跑通一个投顾问答闭环。2. TaoToken 统一 Key 接入让采样请求不再到处找 API Key2.1 为什么需要统一 Key在 MCP 智能投资顾问的采样环节服务端需要通过客户端调用 LLM 生成投资建议。传统做法是直接在采样 handler 里写死某个厂商的 API Key 和 base_url比如阿里云百炼的https://dashscope.aliyuncs.com/compatible-mode/v1。但这样做的问题是换模型要改代码多环境要管多套 Key团队协作时 Key 散落在各个文件里。TaoToken 的思路是提供一个统一的 API 入口把不同模型的调用收敛到同一个 Base URL 和同一把 Key 上。你只需要在采样 handler 里把base_url指向https://taotoken.net/apiapi_key用 TaoToken 控制台生成的 Key模型 ID 按需填写即可。这样无论是 Qwen、Claude 还是其他兼容 OpenAI 接口的模型切换时只改一个model参数。2.2 获取 Key 与配置环境变量先到 TaoToken 控制台创建一个 API Key。地址是https://taotoken.net/console?utm_sourcetaotoken_aicg_blog_endutm_mediumcsdnutm_campaignrewriteutm_contentconsole。创建后复制 Key建议用环境变量管理不要硬编码进代码。在项目根目录创建.env文件TAOTOKEN_API_KEYsk-your-taotoken-key-here TAOTOKEN_BASE_URLhttps://taotoken.net/api然后在 Python 里用os.getenv读取。如果你用的是 conda 或 venv也可以在激活环境后直接exportexport TAOTOKEN_API_KEYsk-your-taotoken-key-here export TAOTOKEN_BASE_URLhttps://taotoken.net/api2.3 采样 handler 中的 TaoToken 接入片段原来的采样 handler 用的是阿里云客户端现在改成 TaoToken 统一入口。核心改动只有三处api_key、base_url、model。下面是一个可直接替换的片段import os from openai import OpenAI client OpenAI( api_keyos.getenv(TAOTOKEN_API_KEY), base_urlos.getenv(TAOTOKEN_BASE_URL, https://taotoken.net/api), ) async def investment_sampling_handler( messages: list, params, ctx, ) - str: try: api_messages [] if params.systemPrompt: api_messages.append({ role: system, content: params.systemPrompt }) for msg in messages: api_messages.append({ role: user, content: msg.content.text }) response client.chat.completions.create( modelqwen-plus, messagesapi_messages, temperature0.7, max_tokens2048, ) return response.choices[0].message.content except Exception as e: print(fLLM采样处理出错: {e}) return f抱歉生成投资建议时出现错误: {str(e)}这里model填qwen-plus只是示例你可以在 TaoToken 的模型列表里换成其他支持的模型 ID。Base URL 固定为https://taotoken.net/api不要加多余路径。Key 从环境变量读取避免泄露。2.4 三类采样策略参数怎么选采样策略直接影响投资建议的风格和稳定性。下面用表格对照三类常见策略的参数配置策略类型temperaturetop_p适用场景建议输出特征稳健保守型0.20.8合规要求高、建议需可复现措辞谨慎资产配置偏保守平衡推荐型0.70.9常规投顾问答兼顾多样性与合理性进取探索型1.00.95创意组合、多方案对比建议发散适合头脑风暴在采样 handler 里你可以根据征询阶段收集到的risk_tolerance字段动态调整temperature。比如用户选conservative就把 temperature 降到 0.2选aggressive就提到 0.9。这样采样策略和用户风险偏好就对齐了。注意TaoToken 的 API 兼容 OpenAI 的 chat completions 接口所以temperature、top_p、max_tokens这些参数都可以直接传。如果你用的模型不支持某个参数接口会返回错误按报错信息去掉即可。3. 可复制配置FastMCP 服务端与客户端完整片段3.1 服务端配置与工具定义先安装依赖pip install fastmcp openai python-dotenv服务端核心是定义InvestmentInfo数据类和两个工具collect_investment_info和get_investment_tips。下面是可复制的服务端片段from dataclasses import dataclass from fastmcp import FastMCP, Context mcp FastMCP(investment-advisor) dataclass class InvestmentInfo: name: str age: int income_level: str risk_tolerance: str investment_period: str investment_amount: float investment_goals: str market_knowledge: str beginner current_investments: str mcp.tool async def collect_investment_info(ctx: Context) - str: 收集用户投资信息并生成投资建议 result await ctx.elicit( message请提供您的投资相关信息我们将为您生成个性化的投资建议, response_typeInvestmentInfo ) if result.action decline: return 用户拒绝提供投资信息无法生成投资建议 elif result.action cancel: return 用户取消了投资咨询 user_info result.data invest_prompt _build_investment_prompt(user_info) try: system_prompt ( 你是一位专业的投资顾问请基于用户提供的信息生成详细、实用的投资建议。 建议应该包括资产配置、具体投资产品推荐、风险提示等内容。 ) llm_response await ctx.sample( system_promptsystem_prompt, messagesinvest_prompt ) llm_text llm_response.text if hasattr(llm_response, text) else str(llm_response) return _format_investment_advice(user_info, llm_text) except Exception as e: return f生成投资建议时出现错误: {str(e)} mcp.tool async def get_investment_tips(ctx: Context) - str: 获取通用投资小贴士 tips [ 分散投资不要把鸡蛋放在一个篮子里, 定期定额投资平摊成本风险, 长期投资通常比短期投机更稳健, 了解自己的风险承受能力理性投资, 保持适当的现金储备以应对紧急情况, ] return 投资小贴士\n \n.join([f- {tip} for tip in tips]) if __name__ __main__: mcp.run(transportstreamable-http, host127.0.0.1, port8003)_build_investment_prompt和_format_investment_advice是两个辅助函数前者把InvestmentInfo拼成提示词后者把 LLM 返回的文本包装成报告格式。你可以按自己的模板调整。3.2 客户端配置与征询 handler客户端需要注册两个 handlerelicitation_handler负责和用户交互收集信息sampling_handler负责调用 LLM。下面是可复制的客户端片段import asyncio from fastmcp import Client from fastmcp.client.elicitation import ElicitResult async def investment_elicitation_handler(message: str, response_type: type, params, context): print(f\n{message}) print(\n请填写以下投资相关信息) try: name input(姓名: ).strip() if not name: return ElicitResult(actiondecline) age_input input(年龄: ).strip() if not age_input.isdigit(): print(年龄必须是数字) return ElicitResult(actiondecline) age int(age_input) income_level input(收入水平 (low/medium/high): ).strip() risk_tolerance input(风险承受能力 (conservative/moderate/aggressive): ).strip() investment_period input(投资期限 (short_term/medium_term/long_term): ).strip() investment_amount float(input(投资金额元: ).strip()) investment_goals input(投资目标逗号分隔: ).strip() market_knowledge input(市场知识水平 (beginner/intermediate/advanced): ).strip() current_investments input(当前投资情况可选: ).strip() confirm input(\n信息是否正确(y/n): ).strip().lower() if confirm not in (y, yes): return ElicitResult(actiondecline) return response_type( namename, ageage, income_levelincome_level, risk_tolerancerisk_tolerance, investment_periodinvestment_period, investment_amountinvestment_amount, investment_goalsinvestment_goals, market_knowledgemarket_knowledge, current_investmentscurrent_investments, ) except KeyboardInterrupt: return ElicitResult(actioncancel) except Exception as e: print(f\n输入处理出错: {e}) return ElicitResult(actiondecline) async def main(): async with Client( http://127.0.0.1:8003/mcp, elicitation_handlerinvestment_elicitation_handler, sampling_handlerinvestment_sampling_handler, ) as mcp_client: await mcp_client.ping() print(已连接到投资顾问服务器 (HTTP模式)) tools await mcp_client.list_tools() print(f\n可用功能: {len(tools)} 个) for tool in tools: print(f - {tool.name}: {tool.description}) while True: print(\n请选择服务) print(1. 获取个性化投资建议) print(2. 查看投资小贴士) print(3. 退出) choice input(\n请输入选择 (1-3): ).strip() if choice 1: result await mcp_client.call_tool(collect_investment_info) print(\n投资建议结果) print(result.content[0].text) elif choice 2: tips_result await mcp_client.call_tool(get_investment_tips) print(\n tips_result.content[0].text) elif choice 3: print(\n感谢使用投资顾问系统) break else: print(无效选择请重新输入) if __name__ __main__: asyncio.run(main())3.3 配置文件与启动命令如果你用 Claude Code 或 Cline 这类支持 MCP 的客户端可以写一个mcp.json配置{ mcpServers: { investment-advisor: { url: http://127.0.0.1:8003/mcp, transport: streamable-http } } }启动顺序先跑服务端python investment_advisor_server.py再跑客户端python investment_advisor_client.py。服务端监听 8003 端口客户端通过 HTTP 连接。提示如果你在 Cline 或 Claude Code 里接入Base URL 填https://taotoken.net/apiKey 填 TaoToken 控制台生成的 KeyModel ID 填你选的模型如qwen-plus。这三件套缺一不可否则采样请求会失败。4. 验证请求与预期输出一次完整的投顾问答闭环4.1 服务端启动验证在终端执行python investment_advisor_server.py预期输出INFO: Started server process [12345] INFO: Waiting for application startup. INFO: Application startup complete. INFO: Uvicorn running on http://127.0.0.1:8003 (Press CTRLC to quit)看到Uvicorn running就说明服务端起来了。如果端口被占用改mcp.run里的port参数即可。4.2 客户端交互验证另开一个终端执行python investment_advisor_client.py预期输出已连接到投资顾问服务器 (HTTP模式) 可用功能: 2 个 - collect_investment_info: 收集用户投资信息并生成投资建议 - get_investment_tips: 获取通用投资小贴士 请选择服务 1. 获取个性化投资建议 2. 查看投资小贴士 3. 退出 请输入选择 (1-3): 1选择 1 后征询 handler 会依次提示你输入姓名、年龄、收入水平、风险承受能力、投资期限、投资金额、投资目标、市场知识水平、当前投资情况。输入完成后确认客户端会把信息通过 MCP 协议回传给服务端服务端再通过采样 handler 调用 TaoToken 的 API 生成建议。4.3 采样请求的预期返回采样 handler 收到请求后会向https://taotoken.net/api发起 chat completions 请求。如果 Key 和 Base URL 配置正确你会看到类似下面的返回投资建议结果 投资建议报告 客户yuan 投资金额20000.0元 投资期限medium_term 风险偏好aggressive 个性化投资建议 根据您提供的详细信息35岁、中等收入、进取型风险偏好、中期投资期限3-5年、 20,000元本金、目标为财富增长、市场知识advanced我为您定制以下中期投资方案 1. 资产配置建议 - 全球股票型ETF / 成长型主动基金60%¥12,000 - 行业主题基金20%¥4,000 - 黄金/大宗商品ETF10%¥2,000 - 现金及货币基金10%¥2,000 2. 具体投资产品推荐 ... 3. 风险控制措施 ...如果返回的是「生成投资建议时出现错误」先检查环境变量TAOTOKEN_API_KEY是否生效再检查base_url是否写成了https://taotoken.net/api不要带多余路径。4.4 投资小贴士工具验证选择 2 会直接返回预设的小贴士列表不经过 LLM 采样。这个工具用来验证 MCP 工具调用链路是否正常如果它能返回内容说明客户端和服务端的连接没问题。5. 本篇常见错排查401、local proxy failed、reading choices、OAuth5.1 401 Unauthorized报错原文openai.AuthenticationError: Error code: 401 - {error: {message: Invalid API key, type: invalid_request_error}}原因TaoToken 的 API Key 没配置或配置错误。排查步骤先在终端echo $TAOTOKEN_API_KEY确认环境变量有值再检查.env文件是否被python-dotenv加载最后确认 Key 没有多余空格或换行。如果用的是 Claude Code 或 Cline检查mcp.json里的 Key 字段是否填对。5.2 local proxy failed报错原文Error: local proxy failed: connection refused原因客户端连不上服务端。排查确认服务端已经启动并监听 8003 端口确认客户端里的 URL 是http://127.0.0.1:8003/mcp而不是https如果服务端跑在容器里检查端口映射。5.3 reading choices 相关报错报错原文AttributeError: NoneType object has no attribute choices或IndexError: list index out of range原因采样 handler 里response.choices[0]取不到值。常见于 API 返回了错误结构但没抛异常或者model参数填了一个不存在的模型 ID。排查打印完整的response对象看结构确认model填的是 TaoToken 支持的模型 ID检查messages列表是否为空。5.4 OAuth 相关报错报错原文OAuth error: invalid_client或OAuth callback failed原因如果你在 Claude Code 或 Cline 里用 OAuth 方式接入但回调地址或 client 配置不对。排查确认mcp.json里用的是urltransport方式而不是 OAuth如果必须用 OAuth检查回调端口是否被占用。对于 TaoToken 接入推荐直接用 API Key 方式不走 OAuth。5.5 征询 handler 返回值类型错误报错原文TypeError: ElicitResult() argument after ** must be a mapping原因征询 handler 返回的不是ElicitResult或response_type实例。排查确认decline和cancel分支返回的是ElicitResult(actiondecline)或ElicitResult(actioncancel)成功分支返回的是response_type(...)实例字段名要和InvestmentInfo数据类一致。注意如果你在 Cline MCP 或 Claude Code 里接入Base URL、Key、Model ID 三件套必须同时配置。只填 Key 不填 Base URL请求会打到默认地址导致 401只填 Base URL 不填 Model ID采样会报模型不存在。6. 把投顾闭环跑通之后还能怎么用这套 MCP 智能投资顾问的骨架跑通后你可以把征询字段换成保险咨询、理财规划、甚至健康问卷采样 handler 里的 system prompt 换一换就是一个新的垂直场景工具。TaoToken 统一 Key 的好处在这里体现得很明显换模型不用改代码只改一个model参数。如果你想把采样策略做得更细可以在征询阶段多收集一个risk_tolerance字段然后在采样 handler 里根据它动态设置temperature。保守型用户给 0.2进取型给 0.9这样生成的投资建议风格会和用户偏好对齐。需要长期跑编码或 Agent 类任务的可以看看 Coding Planhttps://taotoken.net/coding-plan?utm_sourcetaotoken_aicg_blog_endutm_mediumcsdnutm_campaignrewriteutm_contentcoding-plan。想先验证模型对话效果的直接去模型对话页https://taotoken.net/chat?utm_sourcetaotoken_aicg_blog_endutm_mediumcsdnutm_campaignrewriteutm_contentchat。接入文档在https://taotoken.net/doc?utm_sourcetaotoken_aicg_blog_endutm_mediumcsdnutm_campaignrewriteutm_contentdocAPI Key 管理在https://taotoken.net/api-keys?utm_sourcetaotoken_aicg_blog_endutm_mediumcsdnutm_campaignrewriteutm_contentapi-keys。最后留一个实用技巧在采样 handler 里加一层重试逻辑当response.choices为空时自动重试一次能减少偶发的空返回。代码片段for attempt in range(2): response client.chat.completions.create( modelqwen-plus, messagesapi_messages, temperature0.7, ) if response.choices: return response.choices[0].message.content return 模型返回为空请稍后重试这样即使遇到网络抖动或模型侧临时异常投顾问答闭环也不会直接断掉。