数字货币管理代理

一个基于Spring Boot的AI代理,用于管理数字货币数据并通过Azure OpenAI提供投资智能分析,同时集成了MCP协议以实现标准化API暴露。

  • by Ramanjaneyareddy
  • Java
  • 本地部署
  • 更新于
在 GitHub 查看 Ramanjaneyareddy/digitalcurrency-mcp-agent

使用说明

数字货币管理代理

与MCP(模型上下文协议)集成

作者 Ramanjaneya Reddy S
版本: 1.0.0
堆栈: Java 21·Spring Boot 3.3.7·Spring AI 1.0.0·Azure OpenAI·MCP


目录

  1. 项目概述
  2. 技术栈
  3. 系统架构
  4. 组件设计
  5. MCP集成设计
  6. 数据模型
  7. API 参考
  8. MCP工具参考
  9. 请求流程图
  10. 配置指南
  11. 运行项目
  12. 连接MCP客户端
  13. 工程决策与问题解决
  14. 未来路线图

1.工程概况

这个项目是 开发就绪的AI Agent 基于Spring Boot构建,可管理 数字货币数据,并通过Azure OpenAI提供人工智能驱动的投资智能。

随后,它被扩展为 MCP(模型上下文协议) --创建了一个开放标准 通过Anthropic-展示代理商作为标准化、可发现的API的能力 任何兼容MCP的AI客户端都可以连接和使用。

系统做什么

  • 在数据库中存储和管理数字货币数据(价格、市值、时间戳)
  • 为货币管理提供完整的CRUD REST API
  • 通过Azure OpenAI GPT提供三种基于AI的分析功能:
    • 个别货币投资分析
    • 整个投资组合的市场趋势预测
    • 投资组合优化建议
  • 将所有AI功能公开为 MCP工具 --允许克劳德桌面, 其他AI代理和IDE插件以编程方式调用它们

为什么MCP很重要

在MCP之前,每个AI集成都需要双方的自定义代码。 MCP对合同进行标准化:

Without MCP:  Agent A  <--custom code-->  Agent B  <--different custom code-->  Agent C
With MCP:     Agent A  <--MCP protocol-->  Agent B  <--MCP protocol-->           Agent C

这与REST为web服务所做的转变相同——一种通用协议 每个参与者都在发言,而不是到处定制集成。


屏幕截图:

2.技术栈

层 技术 版本 目的
语言 Java 21 主要语言
框架 Spring Boot 3.3.7 应用框架
AI框架 Spring AI 1.0.0 MCP服务器,工具注册
LLM提供商 Azure OpenAI(GPT) SDK 1.0.0-beta13 人工智能分析和预测
HTTP客户端 OkHttp(通过azure core HTTP OkHttp) 由BOM管理 阻止HTTP,无Netty冲突
持久性 Spring Data JPA 由Boot管理 ORM和存储库层
数据库 H2(内存中) 由Boot管理 开发数据库
验证 雅加达验证 由Boot管理 请求验证
构建 Maven 3.x 构建和依赖关系管理
协议 MCP over SSE 1.0.0 AI工具互操作性

密钥依赖设计决策——Netty上的OkHttp

Azure OpenAI SDK默认使用Netty进行HTTP传输。Spring AI MCP服务器 还使用Reactor Netty。当两者都在类路径上时,它们共享一个Netty事件 跨不兼容的线程上下文循环注册表(Spring MVC servlet线程vs 反应堆NIO线程),导致运行时失败。

解决方案: 排除 azure-core-http-netty 和使用 azure-core-http-okhttp 相反。OkHttp是纯阻塞的,没有事件循环——它在任何 线程,包括Spring MVC的servlet线程。


3.系统架构

高级体系结构

+------------------------------------------------------------------+
|                    CLIENT LAYER                                  |
|                                                                  |
|  REST Clients          MCP Clients                               |
|  (Postman, browser,    (Claude Desktop, other Spring AI agents,  |
|   frontend apps)        IDE plugins like Cursor/VS Code)         |
+--------+-----------------------+----------------------------------+
         |                       |
         | HTTP REST             | MCP over SSE (HTTP)
         |                       |
+--------v-----------------------v----------------------------------+
|                    SPRING BOOT APPLICATION                       |
|                         (port 8080)                              |
|                                                                  |
|  +------------------+      +--------------------------------+    |
|  | REST Controllers |      |  MCP Server Layer              |    |
|  |                  |      |  (Spring AI MCP)               |    |
|  | /api/currencies  |      |  GET  /sse        (connect)    |    |
|  | /api/ai          |      |  POST /mcp/message (tool call) |    |
|  | /api/mcp/info    |      |  GET  /api/mcp/info            |    |
|  +--------+---------+      +---------------+----------------+    |
|           |                                |                     |
|           +--------------------------------+                     |
|                            |                                     |
|              +-------------v--------------+                      |
|              |      Service Layer         |                      |
|              |                            |                      |
|              |  DigitalCurrencyService    |                      |
|              |  AzureAiService            |                      |
|              |  CurrencyMcpTools          |                      |
|              +------+-----------+---------+                      |
|                     |           |                                |
|            +--------v---+   +---v-----------+                   |
|            | Repository |   | Azure OpenAI  |                   |
|            | (JPA)      |   | Client        |                   |
|            +--------+---+   | (OkHttp)      |                   |
|                     |       +---+-----------+                   |
|            +--------v---+       |                               |
|            | H2 Database|       | HTTPS                         |
|            | (in-memory)|       |                               |
|            +------------+   +---v---------------------------+   |
|                             | Azure OpenAI Service (cloud)  |   |
|                             | GPT deployment                |   |
|                             +-------------------------------+   |
+------------------------------------------------------------------+

包结构

com.azure.digitalcurrency
|
+-- AzureAiCurrencyApplication.java     Spring Boot entry point
|
+-- config/
|   +-- DataInitializer.java            Seeds 5 sample currencies on startup
|
+-- model/
|   +-- DigitalCurrency.java            JPA entity (id, code, name, value, marketCap)
|
+-- repository/
|   +-- DigitalCurrencyRepository.java  JPA repository with custom queries
|
+-- service/
|   +-- DigitalCurrencyService.java     Business logic + orchestration
|   +-- AzureAiService.java             Azure OpenAI client wrapper
|
+-- controller/
|   +-- DigitalCurrencyController.java  CRUD REST endpoints (/api/currencies)
|   +-- AiAnalysisController.java       AI REST endpoints (/api/ai)
|   +-- McpInfoController.java          MCP info endpoint (/api/mcp/info)
|
+-- mcp/
    +-- CurrencyMcpTools.java           @Tool definitions — MCP tool implementations
    +-- McpServerConfig.java            Registers tools with Spring AI MCP server

4.组件设计

4.1数字货币(实体)

核心域对象,映射到 digital_currency 桌子。

字段 类型 约束 描述
id Long PK,自动生成 内部标识符
currencyCode String 唯一,不为空 例如“BTC”、“ETH”
currencyName String 非空 例如“比特币”
currentValue BigDecimal 非空、正、精度(25.2) 价格(美元)
marketCap BigDecimal 非空、正、精度(25.2) 市值(美元)
createdAt LocalDateTime 持久化时自动 创建时间戳
updatedAt LocalDateTime 更新时自动 上次更新时间戳

BigDecimal 故意用于货币价值-- double 和 float 不能精确地表示小数(IEEE 754二进制浮点), 这会导致财务计算中的舍入误差。

4.2数字货币存储库

扩展 JpaRepository<DigitalCurrency, Long> 并补充道:

Optional<DigitalCurrency> findByCurrencyCode(String currencyCode);
List<DigitalCurrency> findByCurrencyNameContainingIgnoreCase(String name);

@Query("SELECT dc FROM DigitalCurrency dc ORDER BY dc.marketCap DESC")
List<DigitalCurrency> findAllOrderByMarketCapDesc();

@Query("SELECT dc FROM DigitalCurrency dc ORDER BY dc.currentValue DESC")
List<DigitalCurrency> findAllOrderByCurrentValueDesc();

Spring Data JPA在运行时根据方法名生成SQL实现 和JPQL注释——不需要样板SQL。

4.3 AzureAiService

封装Azure OpenAI SDK,并提供三种AI操作。 每种方法都遵循相同的模式:

1. Build system message  (defines AI persona/role)
2. Build user prompt     (injects currency data from DB)
3. Call Azure OpenAI     (getChatCompletions with deployment name)
4. Extract response text (choices[0].message.content)
5. Return or handle error with descriptive message

关键设计选择——可配置部署名称: Azure OpenAI使用部署名称(由用户在Azure门户中设置), 不是型号名称。将其作为财产(azure.openai.deployment-name) 避免了硬编码,并使服务在Azure订阅之间可移植。

4.4数字货币服务

控制器/MCP工具和存储库/AI服务之间的编排层。 责任:

  • 所有存储库访问都通过此服务进行(没有来自控制器的直接存储库调用)
  • 构造传递给AI提示的数据上下文
  • 将AI调用限制在前5种货币,以控制代币使用

4.5数据初始化器

实现 CommandLineRunner --种子5种货币(BTC、ETH、ADA、DOT、SOL) 如果表为空,则在首次启动时使用实际值。这意味着 应用程序在启动后立即可用,无需手动输入数据。


5.MCP集成设计

5.1什么是MCP?

模型上下文协议(MCP)是由Anthropic创建的开放标准 定义AI代理如何在 结构化、可发现的方式。

将其视为AI工具集成的REST标准:

  • REST标准化了系统如何通过HTTP公开数据
  • MCP规范了AI代理如何向LLM公开可调用工具

5.2本项目的MCP架构

此应用程序充当 MCP服务器。它暴露了任何工具 MCP客户端(Claude Desktop,另一个Spring AI代理,IDE插件)可以 发现并呼叫。

MCP Client                          MCP Server (this app)
    |                                       |
    |-- GET /sse --------------------------->|  (1) Establish SSE connection
    |<-- SSE stream opened ------------------|
    |                                       |
    |-- POST /mcp/message                   |
    |   { method: "tools/list" } ---------->|  (2) Discover available tools
    |<-- { tools: [...6 tools...] } ---------|
    |                                       |
    |-- POST /mcp/message                   |
    |   { method: "tools/call",             |
    |     name: "analyze_investment",       |
    |     arguments: {currencyCode:"BTC"}} ->|  (3) Call a tool
    |                                       |
    |                    CurrencyMcpTools.analyzeInvestment("BTC")
    |                           |
    |                    DigitalCurrencyService.getInvestmentAnalysis("BTC")
    |                           |
    |                    AzureAiService.analyzeInvestmentOpportunity(...)
    |                           |
    |                    Azure OpenAI API call (HTTPS)
    |                           |
    |<-- { content: "analysis text..." } ----|  (4) Return result

5.3@Tool注册的工作原理

Spring AI扫描 CurrencyMcpTools 启动时和每个 @Tool 方法:

  1. 读取方法名称, @Tool(name=...),以及 @Tool(description=...)
  2. 读取每个带注释的参数 @ToolParam(description=...)
  3. 使用Java反射生成 JSON 模式 对于参数
  4. 在MCP服务器的工具注册表中注册该工具

当客户来电时 tools/list,Spring AI返回所有注册的工具 包含它们的名称、描述和参数模式——格式为 LLM能够理解并推理决定调用哪个工具。

5.4传输:SSE(服务器发送事件)

MCP支持两种传输方式。此项目使用 基于HTTP的SSE:

运输 用例
Stdio 本地过程通信(例如CLI工具)
SSE 基于网络,微服务友好(此处使用)

选择SSE是因为:

  • 通过标准HTTP工作——无需WebSocket升级
  • 防火墙/代理友好
  • 适用于微服务部署
  • Spring Boot现有的HTTP服务器本机处理它

5.5 McpServerConfig

桥接的单一配置类 CurrencyMcpTools 进入 Spring AI MCP机械:

@Bean
public ToolCallbackProvider currencyToolCallbackProvider(CurrencyMcpTools tools) {
    return MethodToolCallbackProvider.builder()
            .toolObjects(tools)
            .build();
}

MethodToolCallbackProvider 使用反射来扫描经过的物体, 查找所有 @Tool 方法,并注册它们。这是唯一需要的接线-- Spring AI处理其他一切。


6.数据模型

实体关系

+---------------------------+
|     digital_currency      |
+---------------------------+
| id           BIGINT  PK   |
| currency_code VARCHAR(255) |  UNIQUE
| currency_name VARCHAR(255) |
| current_value DECIMAL(25,2)|
| market_cap    DECIMAL(25,2)|
| created_at    TIMESTAMP   |
| updated_at    TIMESTAMP   |
+---------------------------+

样本数据(启动时播种)

代码 名称 价值(美元) 市值(美元)
BTC 比特币 45000.00美元 850000000000美元
ETH 以太坊 3200.00美元 385000000美元
SOL 索拉纳 180.00美元 550000000美元
ADA 卡尔达诺 1.25美元 420亿美元
DOT 波尔卡多特 25.50美元 250亿美元

7.API参考

货币CRUD端点

方法 URL 描述 响应
得到 /api/currencies 列出所有货币 200+数组
得到 /api/currencies/{id} 按数据库ID获取 200/404
得到 /api/currencies/code/{code} 按货币代码获取 200/404
得到 /api/currencies/search?name=bit 按名称搜索(不区分大小写) 200+数组
得到 /api/currencies/top-by-market-cap 所有货币,按市值desc 200+数组排序
得到 /api/currencies/top-by-value 所有货币,按价格降序排序 200+数组
职位 /api/currencies 创建新货币 201/400
PUT /api/currencies/{id} 更新现有货币 200/404
删除 /api/currencies/{id} 删除货币 204/404

POST/PUT请求体:

{
  "currencyCode": "BTC",
  "currencyName": "Bitcoin",
  "currentValue": 45000.00,
  "marketCap": 850000000000
}

AI分析端点

方法 URL 描述
得到 /api/ai/analysis/{currencyCode} 一种货币的人工智能投资分析
得到 /api/ai/market-predictions 所有货币的AI市场趋势预测
得到 /api/ai/portfolio-optimization 人工智能投资组合优化建议

示例响应--/api/ai/analysis/BTC:

{
  "currencyCode": "BTC",
  "analysis": "Bitcoin (BTC) Analysis:\n\n1) Market Trends: Bitcoin continues to..."
}

MCP信息端点

方法 URL 描述
得到 /api/mcp/info 返回MCP服务器详细信息和工具列表

MCP协议端点(由MCP客户端自动使用)

方法 URL 描述
得到 /sse MCP客户端的SSE连接端点
职位 /mcp/message MCP JSON-RPC消息处理程序

8.MCP工具参考

所有六个工具都通过MCP公开,并可由任何MCP客户端调用。

分析投资

说明: 为单一货币生成人工智能驱动的投资分析。
参数: currencyCode (字符串)--例如“BTC”、“ETH”、“SOL”
退货: JSON格式 currencyCode 和 analysis 领域
AI内容包括: 市场趋势、风险评估、投资建议、潜在回报、时间范围

预测市场趋势

说明: 数据库中所有货币的AI市场趋势预测。
参数: 无
退货: JSON格式 predictions 领域
AI内容包括: 短期(1-3个月)展望、中期(3-12个月)前景、价格影响因素、风险因素

优化投资组合

说明: 基于所有跟踪货币的AI投资组合优化建议。
参数: 无
退货: JSON格式 optimization 领域
AI内容包括: 资产配置、多元化战略、风险管理、再平衡频率

get_current数据

说明: 从数据库中检索货币的原始存储数据。
参数: currencyCode (字符串)
退货: JSON,包含代码、名称、当前值、市值、更新时间

list_货币

说明: 按市值顺序列出所有跟踪的货币。
参数: 无
退货: 带计数的JSON货币数组

比较货币

说明: 两种货币的并排AI比较。
参数: currencyCodeA (字符串), currencyCodeB (字符串)
退货: JSON,包含货币数据对象和 aiComparison 分析


9.请求流程图

流程1:直接REST调用——GET/api/ai/分析/BTC

Client
  |
  | GET /api/ai/analysis/BTC
  v
AiAnalysisController.getInvestmentAnalysis("BTC")
  |
  v
DigitalCurrencyService.getInvestmentAnalysis("BTC")
  |
  +-- DigitalCurrencyRepository.findByCurrencyCode("BTC")
  |       |
  |       v
  |   H2 Database
  |       |
  |   Returns: DigitalCurrency{BTC, Bitcoin, 45000, 850B}
  |
  +-- AzureAiService.analyzeInvestmentOpportunity("BTC", "Bitcoin", 45000, 850B)
          |
          +-- Build ChatRequestMessages (system + user prompt with data)
          |
          +-- OpenAIClient.getChatCompletions(deploymentName, options)
                  |
                  | HTTPS POST (OkHttp blocking call)
                  v
              Azure OpenAI API
                  |
              Returns: ChatCompletions
                  |
          Extract choices[0].message.content
          |
  Return analysis string
  |
  v
ResponseEntity { "currencyCode": "BTC", "analysis": "..." }
  |
  v
Client receives JSON response

流程2:MCP工具调用——通过Claude Desktop进行分析投资

Claude Desktop (MCP Client)
  |
  | User types: "Analyse Bitcoin from my database"
  | LLM decides: call analyze_investment tool
  |
  | POST /mcp/message
  | { "method": "tools/call",
  |   "params": { "name": "analyze_investment",
  |               "arguments": { "currencyCode": "BTC" } } }
  v
Spring AI MCP Server
  |
  +-- Looks up registered tool "analyze_investment"
  +-- Finds: CurrencyMcpTools.analyzeInvestment(String)
  +-- Calls: currencyMcpTools.analyzeInvestment("BTC")
  |
  v
CurrencyMcpTools.analyzeInvestment("BTC")
  |
  v
DigitalCurrencyService.getInvestmentAnalysis("BTC")
  | [same as Flow 1 from here]
  v
AzureAiService → Azure OpenAI API
  |
  v
Returns analysis JSON string
  |
  v
Spring AI MCP Server wraps result in MCP response format
  |
  v
Claude Desktop receives result
  |
  v
Claude presents analysis to user in natural language

10.配置指南

所有配置都在 src/main/resources/application.properties.

必需--Azure OpenAI凭据

# Your Azure OpenAI resource endpoint (must end with /)
azure.openai.endpoint=https://YOUR-RESOURCE-NAME.openai.azure.com/

# API key from Azure Portal > Your OpenAI resource > Keys and Endpoint
azure.openai.api-key=YOUR_API_KEY_HERE

# The DEPLOYMENT NAME from Azure OpenAI Studio > Deployments
# This is the name YOU gave your deployment — NOT the model name
# e.g. if you named your deployment "gpt-35-turbo", use that exactly
azure.openai.deployment-name=YOUR_DEPLOYMENT_NAME

如何查找部署名称

  1. 首选https://oai.azure.com(Azure OpenAI工作室)
  2. 选择您的资源
  3. 点击 部署 在左侧菜单中
  4. 复制中的值 部署名称 列(不是模型列)

MCP服务器配置

spring.ai.mcp.server.enabled=true
spring.ai.mcp.server.name=digital-currency-agent
spring.ai.mcp.server.version=1.0.0
spring.ai.mcp.server.transport=SSE

数据库配置(H2——开发)

spring.datasource.url=jdbc:h2:mem:digitalcurrency
spring.h2.console.enabled=true
spring.h2.console.path=/h2-console

访问H2控制台http://localhost:8080/h2-控制台
JDBC网址: jdbc:h2:mem:digitalcurrency |用户名: sa |密码:(空)


11.项目运行

先决条件

  • Java 21+
  • Maven 3.6+
  • 已部署GPT模型的Azure OpenAI资源

步骤

# 1. Clone or extract the project
cd cd digitalcurrency-mcp-agent

# 2. Set your Azure credentials in:
#    src/main/resources/application.properties

# 3. Build
mvn clean install

# 4. Run
mvn spring-boot:run

验证它是否正在运行

# Should return list of 5 seeded currencies
curl http://localhost:8080/api/currencies

# Should return AI market predictions
curl http://localhost:8080/api/ai/market-predictions

# Should return MCP server info and tool list
curl http://localhost:8080/api/mcp/info

12.连接MCP客户端

克劳德桌面版

编辑(或创建)Claude Desktop配置文件:

  • 雨衣: ~/Library/Application Support/Claude/claude_desktop_config.json
  • 窗户: %APPDATA%\Claude\claude_desktop_config.json
{
  "mcpServers": {
    "digital-currency-agent": {
      "transport": "sse",
      "url": "http://localhost:8080/sse"
    }
  }
}

重新启动克劳德桌面。工具图标(🔧) 将显示6个可用工具。

然后你可以自然地问克劳德:

  • “我的货币的市场预测是什么?”
  • “从我的数据库对比比特币和以太坊”
  • “我应该根据我的数据投资Solana吗?”

Claude将调用相应的工具,从Spring Boot中获取响应 代理,并以对话的方式呈现。

另一个Spring AI代理

将此添加到其他代理的 application.yml:

spring:
  ai:
    mcp:
      client:
        enabled: true
        toolcallback:
          enabled: true
        sse:
          connections:
            digital-currency:
              url: http://localhost:8080

Spring AI将自动发现并注册该代理LLM的所有6个工具。


13.工程决策和问题解决

在开发过程中解决了三个真正的工程挑战:

问题1-Java类型推理失败(编译错误)

错误:

incompatible types: Map<String, Object & Serializable & Comparable<?>>
cannot be converted to Map<String, Object>

原因: Map.of() 使用混合值类型(String+BigDecimal)会导致Java 类型推断,以生成太窄而无法分配的交集类型 Map<String, Object>.

解决方案: 替换 Map.of() 随着 new HashMap<>() +明确的 put() 电话 无论不同类型的值混合在哪里。 HashMap 没有类型推理 在建设中——它总是 HashMap<String, Object>.

问题2-Netty事件循环冲突(运行时错误)

错误:

channel not registered to an event loop

原因: Azure OpenAI SDK默认使用Netty进行HTTP传输。 MCP服务器依赖关系(spring-ai-starter-mcp-server-webmvc)也 将Reactor Netty拉到类路径中。两个Netty环境共享 全局事件循环注册表,但在不兼容的线程上下文中运行-- Spring MVC的servlet线程与Reactor的NIO线程。第一次通话 靠运气成功;来自错误线程上下文的后续调用失败。

解决方案: 两部分修复:

  1. 排除 azure-core-http-netty 中的Azure AI依赖关系 pom.xml
  2. 添加 azure-core-http-okhttp 并显式配置客户端:
    .httpClient(new OkHttpAsyncHttpClientBuilder().build())
    
    OkHttp是纯阻塞的——没有事件循环,没有线程上下文冲突。

问题3-Azure OpenAI 500错误

错误:

{ "code": 500, "message": "Internal Server Error" }

原因: 代码正在传递 "gpt-3.5-turbo" 作为模型标识符。 Azure OpenAI不使用OpenAI模型名称——它使用 部署名称 由用户在Azure OpenAI Studio中定义。传递未知名称的结果 在Azure的API的500中。

解决方案:

  1. 将部署名称设置为可配置属性: azure.openai.deployment-name
  2. 为每个HTTP状态码(401、404、500)添加了特定的错误消息 未来的配置错误可立即诊断

14.未来路线图

短期

  • PostgreSQL --将H2替换为用于生产的持久数据库
  • 实时价格 -集成CoinGecko或CoinMarketCap API以获取 实时价格和按计划自动更新数据库
  • Spring Security -添加API密钥身份验证以保护终结点

中期

  • 流媒体响应 -使用Azure OpenAI流API进行AI分析 逐令牌流式传输回客户端令牌,而不是等待完整响应
  • 对话记忆 --使用Spring AI ChatMemory 保持上下文 在一个会话中跨越多个问题
  • 其他MCP工具 — update_price, add_currency, set_price_alert

长期

  • 多代理架构 --将此代理作为工具提供程序连接到 高级编排器代理,可以将货币数据与新闻提要相结合, 监管警报和宏观经济指标
  • MCP资源风险 --将货币数据库作为MCP资源公开 (不仅仅是工具),允许客户订阅价格变动通知

基于Spring Boot 3.3.7构建·Spring AI 1.0.0·Azure OpenAI·MCP