Token导航 LogoToken导航TokenDH.com
AI Agent Starter Portfolio Manager logo
AI代理stdio官方级别未说明来源级核验

AI Agent Starter Portfolio Manager

MCP Server

基于AI的交易平台投资组合事件账本API,提供REST和MCP接口,支持自然语言查询和自动化交易管理。

工具数

11

提示词数

0

GitHub Stars

0

资源数

0
AI代理PythonClaudeClaude DesktopClaudeVS Code

安装说明

本站只整理中文说明和来源信息,不托管安装包,也不代用户安装。

作者 / 组织

drewelewis

提供方

drewelewis

最后核验

2026/5/17 20:20

运行时

Python

快速接入

先看主来源和安装命令,再打开仓库或文档;下面只保留这个条目的关键接入事实。

命令预览

python main.py

详细介绍

交易平台AI代理

一个AI驱动的投资组合事件分类账API构建 Microsoft代理框架, 快速API,以及 Azure PostgreSQL --部署到 Azure容器应用 并作为一个 MCP服务器 通过 Azure API管理.

______________________________________________________________________

目录

  1. 概述
  2. 建筑
  3. 项目结构
  4. Azure基础架构
  5. 环境变量
  6. API终点
  7. 数据库模式
  8. APIM MCP网关
  9. 本地开发
  10. 码头工人
  11. 助手脚本
  12. 测试

______________________________________________________________________

概述

交易平台AI代理提供了两个与投资组合事件分类账交互的界面:

表面协议URL
REST APIHTTP/JSONhttps:///
MCP服务器(AI网关)MCP/流式HTTPhttps://ai-learning-apim.azure-api.net/trading-platform-mcp-server/mcp

REST API公开结构化查询端点和自然语言 聊天 由Azure OpenAI支持的代理支持的端点。MCP服务器(托管在Azure API管理中)使所有11个端点都可以被任何MCP兼容客户端发现和调用,这些客户端包括Claude Desktop、VS Code Copilot、自定义代理框架,而无需订阅密钥。

______________________________________________________________________

建筑

┌──────────────────────────────────────────────────────────┐
│  MCP Clients                                             │
│  (Claude Desktop · VS Code Copilot · Custom Agents)      │
└────────────────┬─────────────────────────────────────────┘
                 │  MCP protocol (Streamable HTTP / SSE)
                 ▼
┌──────────────────────────────────────────────────────────┐
│  Azure API Management  (BasicV2+)                        │
│  ai-learning-apim.azure-api.net                          │
│                                                          │
│  ┌─────────────────────────────────────────────────┐     │
│  │ MCP Server: trading-platform-mcp-server         │     │
│  │ path: /trading-platform-mcp-server              │     │
│  │ type: mcp   subscriptionRequired: false         │     │
│  │ 11 tools: health, agentStatus, portfolioSummary │     │
│  │   latestPrice, tradeHistory, accountEvents,     │     │
│  │   tickerEvents, chat, clearSession, insertEvent │     │
│  │   root                                          │     │
│  └──────────────────────┬──────────────────────────┘     │
│                         │ REST proxy                      │
│  ┌────────────────────┐ └──────────────────────────────┐  │
│  │ REST API           │                               │  │
│  │ trading-platform-api                               │  │
│  │ path: /  (root)                                   │  │
│  │ subscriptionRequired: false                       │  │
│  └───────────────────────────────────────────────────┘  │
└────────────────┬─────────────────────────────────────────┘
                 │  HTTPS
                 ▼
┌──────────────────────────────────────────────────────────┐
│  Azure Container Apps                                    │
│  ai-learning-aca  (East US)                              │
│  min-replicas: 1  |  ingress: external  |  port: 8989   │
│                                                          │
│  Trading Platform FastAPI (Python 3.11)                  │
│  ├── GET  /health                                        │
│  ├── GET  /                                              │
│  ├── POST /chat                      ─┐                  │
│  ├── POST /clear_session              ├─ Agent endpoints │
│  ├── GET  /portfolio/{account_id}    ─┘                  │
│  ├── GET  /portfolio/{account_id}/trades                 │
│  ├── GET  /portfolio/{account_id}/events                 │
│  ├── GET  /ticker/{ticker_symbol}/price                  │
│  ├── GET  /ticker/{ticker_symbol}/events                 │
│  ├── POST /events                                        │
│  └── GET  /agent/status                                  │
└──────┬───────────────────┬────────────────────────────────┘
       │                   │
       │ asyncpg           │ azure-identity (DefaultAzureCredential)
       ▼                   ▼
┌─────────────┐   ┌────────────────────────────────────────┐
│  Azure      │   │  Azure OpenAI / AI Foundry             │
│  PostgreSQL │   │  (direct model endpoint)               │
│  Flexible   │   │  Model: gpt-4.1 (or configured)        │
│  Server     │   │  Auth: Managed Identity                │
│  (SSL)      │   └────────────────────────────────────────┘
└─────────────┘

请求流——MCP工具调用(例如。 portfolioSummary)

Client --[MCP call_tool "portfolioSummary" {account_id: "A100"}]--> APIM
APIM   --[GET /portfolio/A100]--> Container Apps
Container Apps --[asyncpg SELECT]--> PostgreSQL
PostgreSQL --[rows]--> Container Apps
Container Apps --[JSON {account_id, positions: [...]}]--> APIM
APIM   --[MCP tool result]--> Client

请求流——通过MCP进行NL聊天

Client --[MCP call_tool "chat" {session_id, message}]--> APIM
              ↓ inbound policy reconstructs JSON body
APIM   --[POST /chat {session_id, message}]--> Container Apps
Container Apps --[agent.run(message, thread)]--> Azure OpenAI
Azure OpenAI --[tool_calls: get_portfolio_summary, ...]-->
  Container Apps executes tools against PostgreSQL
  Container Apps --[final text response]--> APIM
APIM --[MCP tool result {response: "..."}]--> Client

______________________________________________________________________

项目结构

.
├── main.py                          # Uvicorn entry point (port 8989)
├── chat.py                          # Interactive CLI chat client
├── requirements.txt                 # Python dependencies
├── dockerfile                       # Production container image (python:3.11-slim)
├── docker-compose.yaml              # Local stack: API + PostgreSQL + Adminer
├── env.sample                       # Template — copy to .env
│
├── api/
│   ├── main.py                      # FastAPI app — all REST endpoints
│   └── main_with_proxy.py           # Alternative with APIM proxy headers
│
├── agents/
│   └── trading_platform_agent.py   # ChatAgent definition + system prompt
│
├── operations/
│   └── trading_platform_operations.py  # asyncpg queries (connection pool, retry)
│
├── tools/
│   └── trading_platform_tool.py    # ai_function wrappers (agent-callable tools)
│
├── models/
│   └── chat_models.py              # Pydantic request/response models
│
├── data/
│   ├── ddl.sql                      # PostgreSQL schema + indexes
│   ├── portfolio_event_ledger_500.csv  # Synthetic seed data (500 rows)
│   └── portfolio_event_ledger_schema.json
│
├── tests/
│   └── test_mcp.py → (root)        # (see test_mcp.py below)
│
├── test_mcp.py                      # End-to-end MCP server test (8 tools)
│
└── infra/
    └── apim-mcp-body.json          # APIM MCP ARM body reference

______________________________________________________________________

Azure基础架构

所需资源

资源SKU/Tier备注
资源组ai-learning-rg
Azure容器注册表基础+商店 drewl/ai-agent-starter-portfolio-manager
Azure容器应用程序环境消费ai-learning-aca,美国东部
Azure容器应用 (app)--最小副本数:0,端口8989,外部入口
Azure PostgreSQL灵活服务器需要可爆B1ms+SSL, portfolio_event_ledger 桌子
Azure OpenAIAI铸造厂gpt-4.1(或gpt-4o)直接模型端点
Azure API管理基础V2+BasicV2最低要求——MCP服务器功能所需
重要提示: APIM MCP服务器支持(type: "mcp")要求 Basic V2或更高级别。开发人员和消费层不支持此功能。

APIM配置

APIM中配置了两个API:

APIM对象类型路径身份验证
trading-platform-api休息/ (root)匿名
trading-platform-mcp-serverMCP/trading-platform-mcp-server匿名

MCP API创建为 type: mcp 通过Azure门户网站(API管理→ APIs → + 添加API→ MCP服务器)。它自动发现REST后端OpenAPI规范中的11个工具。

管理身份

容器应用程序使用 系统分配的管理身份 具有以下角色分配:

角色范围目的
Cognitive Services OpenAI UserAzure OpenAI资源调用模型端点

身份验证使用 DefaultAzureCredential --Azure中的托管身份, az login 当地。

______________________________________________________________________

环境变量

复制 env.sample.env 并填写:

# ── Azure OpenAI (direct model endpoint) ──────────────────
AZURE_OPENAI_API_ENDPOINT=https://your-resource.openai.azure.com/
MODEL_DEPLOYMENT_NAME=gpt-4.1

# ── Azure AI Foundry (alternative — if using Foundry project endpoint) ──
AZURE_PROJECT_ENDPOINT=https://your-resource.services.ai.azure.com/api/projects/your-project

# ── Azure PostgreSQL Flexible Server ──────────────────────
POSTGRES_HOST=your-server.postgres.database.azure.com
POSTGRES_PORT=5432
POSTGRES_DB=postgres
POSTGRES_USER=your-admin-user
POSTGRES_PASSWORD=your-password
POSTGRES_SSL_MODE=require

# ── API Server ─────────────────────────────────────────────
SERVER_HOST=0.0.0.0
SERVER_PORT=8989
SERVER_RELOAD=false          # true = uvicorn --reload (dev only)
SERVICE_NAME=trading-platform-api
SERVICE_VERSION=1.0.0
SERVER_URL=                  # Public base URL for Swagger UI (e.g. https://your-aca-host)

# ── Docker ─────────────────────────────────────────────────
DOCKER_REPO_NAME=drewl/ai-agent-starter-portfolio-manager

# ── APIM MCP ───────────────────────────────────────────────
APIM_MCP_SERVER_URL=https://ai-learning-apim.azure-api.net/trading-platform-mcp-server/mcp

# ── Azure Credentials (optional — for local dev without az login) ──
AZURE_CLIENT_ID=
AZURE_CLIENT_SECRET=
AZURE_TENANT_ID=

______________________________________________________________________

API终点

基本URL(生产): https://ai-learning-aca.ashycliff-5cba4403.eastus.azurecontainerapps.io\ 交互式文档: /docs

获取 /

服务信息和端点图。

答复:

{
  "service": "trading-platform-api",
  "version": "1.0.0",
  "docs": "/docs",
  "endpoints": { ... }
}

______________________________________________________________________

获取 /health

服务健康检查,包括数据库连接。

答复:

{
  "status": "healthy",
  "service": "trading-platform-api",
  "version": "1.0.0",
  "agent": "ready",
  "database": "connected",
  "framework": "Microsoft Agent Framework"
}

status"healthy" 只有当代理和数据库都准备就绪时。降级为 "degraded" 否则。

______________________________________________________________________

发布 /chat

与交易平台代理进行自然语言聊天。保持完整的会话上下文 session_id.

请求:

{ "session_id": "user-1", "message": "Give me a portfolio summary for account A100" }

答复:

{
  "session_id": "user-1",
  "response": "Account A100 holds 175 shares of MSFT ...",
  "agent": "TradingPlatformAgent"
}

代理可以访问7个工具,并将自动调用它们来回答问题。对话历史记录保存在内存中 session_id.

______________________________________________________________________

发布 /clear_session

清除会话的对话历史记录。

请求:

{ "session_id": "user-1" }

答复:

{ "status": "cleared", "session_id": "user-1" }

______________________________________________________________________

获取 /portfolio/{account_id}

账户的净股票头寸、净成本基础和每个股票代码的最后观察价格。

例子: GET /portfolio/A100

答复:

{
  "account_id": "A100",
  "positions": [
    {
      "account_id": "A100",
      "ticker_symbol": "MSFT",
      "net_shares": 175.0,
      "net_cost": 52830.0,
      "last_price": 416.10,
      "last_event_ts": "2026-02-20T15:00:00+00:00"
    }
  ]
}

计算: net_shares = SUM(BUY shares) - SUM(SELL shares), net_cost = SUM(BUY value) - SUM(SELL value).

______________________________________________________________________

获取 /portfolio/{account_id}/trades

买卖账户的交易历史记录。

查询参数:

参数类型默认值描述
event_typestring--筛选条件 BUYSELL
limitint100最大行数

例子: GET /portfolio/A100/trades?event_type=BUY&limit=5

答复:

{
  "account_id": "A100",
  "event_type": "BUY",
  "trades": [
    {
      "id": 499,
      "account_id": "A100",
      "ticker_symbol": "MSFT",
      "event_ts": "2026-02-03T07:15:00+00:00",
      "event_type": "BUY",
      "shares": 10.0,
      "price_per_share": 349.5,
      "currency": "USD",
      "source": "synthetic"
    }
  ]
}

______________________________________________________________________

获取 /portfolio/{account_id}/events

账户的所有分类账事件(买入、卖出、价格),最新优先。

查询参数:

参数类型默认值描述
limitint100最大行数

答复:

{
  "account_id": "A100",
  "count": 100,
  "events": [ { ... }, ... ]
}

______________________________________________________________________

获取 /ticker/{ticker_symbol}/price

最近观察到的股票市场价格(最新 PRICE 事件)。

例子: GET /ticker/MSFT/price

答复:

{
  "ticker_symbol": "MSFT",
  "price_per_share": 416.10,
  "currency": "USD",
  "event_ts": "2026-02-20T15:00:00+00:00"
}

退货 404 如果自动收报机不存在价格事件。

______________________________________________________________________

获取 /ticker/{ticker_symbol}/events

所有账户的自动收报机的所有分类账事件,最新事件优先。

查询参数:

参数类型默认值描述
limitint100最大行数

答复:

{
  "ticker_symbol": "MSFT",
  "count": 100,
  "events": [ { ... }, ... ]
}

______________________________________________________________________

发布 /events

在分类账中插入新的投资组合事件。

请求:

{
  "account_id": "A100",
  "ticker_symbol": "MSFT",
  "event_ts": "2026-02-22T10:00:00Z",
  "event_type": "BUY",
  "shares": 5.0,
  "price_per_share": 420.0,
  "currency": "USD",
  "source": "api"
}

event_type 必须 BUY, SELL,或 PRICE.使用 shares: 0 价格事件。

答复(201):

{ "status": "created", "id": 501, "account_id": "A100", ... }

______________________________________________________________________

获取 /agent/status

代理功能和已注册的工具列表。

答复:

{
  "agent": "TradingPlatformAgent",
  "status": "ready",
  "tools": [
    { "name": "get_events_by_account", "description": "All events for an account" },
    { "name": "get_events_by_ticker", "description": "All events for a ticker" },
    { "name": "get_portfolio_summary", "description": "Net position + cost basis per ticker" },
    { "name": "get_latest_price", "description": "Most recent PRICE observation" },
    { "name": "get_trade_history", "description": "BUY/SELL history, filterable by type" },
    { "name": "insert_trade_event", "description": "Insert a new ledger event" },
    { "name": "check_database_health", "description": "DB connectivity probe" }
  ]
}

______________________________________________________________________

数据库模式

表: portfolio_event_ledger

CREATE TABLE portfolio_event_ledger (
    id               BIGSERIAL       PRIMARY KEY,
    account_id       VARCHAR(64)     NOT NULL,
    ticker_symbol    VARCHAR(16)     NOT NULL,
    event_ts         TIMESTAMPTZ     NOT NULL,
    event_type       VARCHAR(8)      NOT NULL CHECK (event_type IN ('BUY', 'SELL', 'PRICE')),
    shares           NUMERIC(18, 6)  NOT NULL DEFAULT 0,
    price_per_share  NUMERIC(18, 6)  NOT NULL,
    currency         VARCHAR(8)      NOT NULL,
    source           VARCHAR(128)    NOT NULL,
    created_at       TIMESTAMPTZ     NOT NULL DEFAULT NOW()
);

类型注释
id双周期自动递增PK
account_idVARCHAR(64)例如。 A100, ACC-001
ticker_symbolVARCHAR(16)例如。 MSFT, AAPL
event_ts时间戳事件发生的时间
event_typeVARCHAR(8)BUY / SELL / PRICE
sharesNUMERIC(18,6)股份数量; 0 价格活动
price_per_shareNUMERIC(18,6)交易价格或市场观察
currencyVARCHAR(8)ISO代码,例如。 USD
sourceVARCHAR(128)broker, market-feed, api, synthetic
created_atTIMESTAMPTZ行插入时间戳

索引

-- Primary query pattern: account + time
CREATE INDEX idx_pel_account_ts      ON portfolio_event_ledger (account_id, event_ts DESC);
-- Ticker market queries
CREATE INDEX idx_pel_ticker_ts       ON portfolio_event_ledger (ticker_symbol, event_ts DESC);
-- Event type filtering (P&L)
CREATE INDEX idx_pel_event_type      ON portfolio_event_ledger (event_type);
-- Position roll-up
CREATE INDEX idx_pel_account_ticker  ON portfolio_event_ledger (account_id, ticker_symbol, event_ts DESC);

应用架构: psql -h -U -d postgres -f data/ddl.sql\ 加载种子数据: psql -h -U -d postgres -c "\COPY portfolio_event_ledger FROM 'data/portfolio_event_ledger_500.csv' CSV HEADER"

______________________________________________________________________

APIM MCP网关

端点

https://ai-learning-apim.azure-api.net/trading-platform-mcp-server/mcp

不需要API密钥(subscriptionRequired: false).

MCP工具(11)

工具映射到描述
healthGET /health服务+数据库健康状况
agentStatusGET /agent/status注册工具
portfolioSummaryGET /portfolio/{account_id}净头寸
latestPriceGET /ticker/{ticker_symbol}/price最新市场价格
tradeHistoryGET /portfolio/{account_id}/trades买卖历史
accountEventsGET /portfolio/{account_id}/events所有帐户事件
tickerEventsGET /ticker/{ticker_symbol}/events所有股票交易事件
chatPOST /chatNL与客服聊天
clearSessionPOST /clear_session清除会话历史记录
insertEventPOST /events插入新事件
rootGET /服务信息

使用Python

import asyncio, httpx, os
from dotenv import load_dotenv
from mcp import ClientSession
from mcp.client.streamable_http import streamable_http_client

load_dotenv()
MCP_URL = os.getenv("APIM_MCP_SERVER_URL")

async def main():
    async with httpx.AsyncClient(timeout=120.0) as http:
        async with streamable_http_client(MCP_URL, http_client=http) as (read, write, _):
            async with ClientSession(read, write) as session:
                await session.initialize()
                # List tools
                tools = await session.list_tools()
                # Call a tool
                result = await session.call_tool("latestPrice", {"ticker_symbol": "MSFT"})
                print(result.content[0].text)

asyncio.run(main())

APIM MCP预览——POST正文解决方法

问题: APIM-MCP(2025-03-01-preview)正确代理GET端点的路径/查询参数,但 将MCP工具参数序列化为POST端点的JSON请求体。FastAPI接收一个空正文并返回HTTP 422。

受影响的工具: chat, clearSession, insertEvent

修复: 每个POST操作上的APIM入站策略都会根据APIM转发的查询参数重建JSON正文:


  
    
    
    @{
      try {
        var body = context.Request.Body?.As<JObject>(true);
        if (body != null && body.ContainsKey("session_id")) { return body.ToString(); }
      } catch {}
      var s = context.Request.Url.Query.GetValueOrDefault("session_id", "mcp-session");
      var m = context.Request.Url.Query.GetValueOrDefault("message", "");
      return new JObject(
        new JProperty("session_id", s),
        new JProperty("message", m)
      ).ToString();
    }
    
      application/json
    
  
  
  
  

通过以下方式部署:

# Build policy_body.json: { "properties": { "value": "
...
", "format": "xml" } }
az rest --method PUT \
  --uri "https://management.azure.com/subscriptions/{subId}/resourceGroups/ai-learning-rg/providers/Microsoft.ApiManagement/service/ai-learning-apim/apis/trading-platform-api/operations/chat_chat_post/policies/policy?api-version=2022-08-01" \
  --body "@policy_body.json" \
  --headers "Content-Type=application/json"

______________________________________________________________________

本地开发

先决条件

  • Python 3.11+
  • Azure命令行界面(az login)
  • 访问Azure OpenAI或AI Foundry(AZURE_OPENAI_API_ENDPOINTAZURE_PROJECT_ENDPOINT)
  • PostgreSQL连接(Azure或本地Docker)

设置

# 1. Create and activate virtual environment
_env_create.bat
_env_activate.bat

# 2. Install dependencies
_install.bat

# 3. Copy and fill in environment variables
copy env.sample .env
# Edit .env with your values

# 4. Start the API server locally
python main.py
# → http://localhost:8989/docs

交互式CLI聊天

python chat.py

呈现一个REPL,用于向以下对象发送消息 POST /chat 并打印响应。

______________________________________________________________________

码头工人

构建与运行

# Build image
_build.bat

# Start full stack (API + PostgreSQL + Adminer)
_up.bat

# View logs
_logs.bat

# Stop
_down.bat

服务开始于 _up.bat:

服务端口描述
ai-agent-starter-api8989交易平台API
ai-agent-starter-portfolio-manager-postgres5000→5432PostgreSQL 17
ai-agent-starter-portfolio-manager-adminer8888管理员数据库用户界面

推送到注册表

_push.bat
# Pushes image to DOCKER_REPO_NAME defined in .env

______________________________________________________________________

助手脚本

脚本动作
_env_create.batpython -m venv .venv
_env_activate.bat 激活 .venv
_env_deactivate.bat停用 .venv
_install.batpip install -r requirements.txt
_build.batdocker build
_up.batdocker compose up -d
_down.batdocker compose down
_logs.batdocker compose logs -f
_push.batdocker push 到注册表

______________________________________________________________________

测试

MCP端到端测试

针对实时APIM端点测试所有8个核心MCP工具:

python test_mcp.py

预期产量:

============================================================
  Trading Platform MCP Server Test
  URL: https://ai-learning-apim.azure-api.net/trading-platform-mcp-server/mcp
============================================================
  Connected — MCP session initialized

MCP tools advertised (11): health, agentStatus, chat, ...

[health]           ✅  healthy
[agentStatus]      ✅  7 tools
[portfolioSummary] ✅  1 ticker(s)
[latestPrice]      ✅  MSFT @ 416.10
[tradeHistory]     ✅  67 trades
[accountEvents]    ✅  100 events
[tickerEvents]     ✅  100 events
[chat]             ✅  Agent replied (212 chars)
------------------------------------------------------------
  8/8 passed

需要 APIM_MCP_SERVER_URL.env.

REST API(手动)

# Health
curl https://ai-learning-aca.ashycliff-5cba4403.eastus.azurecontainerapps.io/health

# Portfolio summary
curl https://ai-learning-aca.ashycliff-5cba4403.eastus.azurecontainerapps.io/portfolio/A100

# Latest price
curl https://ai-learning-aca.ashycliff-5cba4403.eastus.azurecontainerapps.io/ticker/MSFT/price

# NL chat
curl -X POST https://ai-learning-aca.ashycliff-5cba4403.eastus.azurecontainerapps.io/chat \
  -H "Content-Type: application/json" \
  -d '{"session_id": "test", "message": "Summarize portfolio A100"}'

______________________________________________________________________

许可证

本项目根据 许可证 文件。

目录标签

目录标签

AI代理PythonClaude本地部署投资组合管理交易平台RESTAPIMCP协议

支持客户端

Claude DesktopClaudeVS Code

接入字段

传输方式(transport,传输协议)

stdio

鉴权方式(authType,认证方式)

session

运行时(runtime,运行环境)

Python

工具数量(toolCount,工具数)

11

资源数量(resourceCount,资源数)

0

提示词数量(promptCount,提示词数)

0

权限和风险

stdiosession部署方式未说明

接入前请确认传输方式、认证方式和部署位置,并根据实际工具能力限制访问范围。

安装前确认

不要直接授予不必要的文件、网络或账号权限;先核对安装命令和配置内容。

来源信息

继续浏览同类 MCP