# BTP Agent - Project Overview ## Vision A CAP TypeScript monorepo hosting an AI agent connected to SAP BTP AI Core, with a UI5 freestyle chat interface, and multiple MCP server modules that give the agent access to BTP APIs. ## Architecture ``` btp-agent/ # monorepo root (npm workspaces) ├── app/ │ └── chat/ # UI5 freestyle chat app ├── db/ # CDS data model (chat history, sessions) ├── srv/ # CAP service (agent host) │ ├── agent.ts # LangGraph agent with AI Core via @sap-ai-sdk/langchain │ ├── mcp/mcp-adapter.ts # MultiServerMCPClient connecting to MCP server modules │ ├── chat-service.ts # CDS service handler (REST/WS endpoints) │ └── chat-service.cds # CDS service definition ├── packages/ │ ├── cf-mcp-server/ # CF V3 API MCP server (odata-mcp-proxy config-only) │ ├── btp-mcp-server/ # BTP Core APIs MCP server (Accounts, Entitlements, Provisioning, XSUAA) │ ├── auditlog-mcp-server/ # Audit Log API MCP server │ └── aicore-mcp-server/ # AI Core API MCP server ├── mta.yaml # MTA deployment descriptor ├── xs-security.json # Shared XSUAA config ├── package.json # Workspaces root └── tsconfig.json ``` ## Key Design Decisions - **Agent framework**: LangGraph StateGraph with `AzureOpenAiChatClient` from `@sap-ai-sdk/langchain` - **MCP servers**: Each is a zero-code module using `odata-mcp-proxy` (npm package) with only a JSON config file - **MCP transport**: stdio for local dev, http for production - **MCP-to-agent wiring**: `@langchain/mcp-adapters` `MultiServerMCPClient` spawns each MCP server and exposes tools to the LangGraph agent - **UI5 chat app**: Freestyle UI5 TypeScript app in `app/chat/`, integrated via `cds-plugin-ui5` for dev-time - **Data persistence**: CDS entities for chat sessions/messages, backed by SQLite (dev) / HANA (prod) - **Streaming**: WebSocket support for real-time token output to the chat UI ## Key Dependencies - `@sap/cds` + `@sap/cds-dk` — CAP runtime + dev kit - `@sap-ai-sdk/langchain` — AI Core bridge to LangChain - `@langchain/langgraph` — agent framework (StateGraph, MemorySaver, ToolNode) - `@langchain/mcp-adapters` — MCP tool integration (MultiServerMCPClient) - `odata-mcp-proxy` — config-driven MCP server for OData/REST APIs (used by all MCP modules) - `cds-plugin-ui5` — dev-time UI5 integration with CAP - `zod` — schema validation for tools ## Reference Repos - Agent pattern: https://github.com/SAP/ai-sdk-js/blob/main/sample-code/src/tutorials/travel-itinerary-agent.ts - MCP adapter pattern: same repo, `sample-code/src/tutorials/mcp/mcp-adapter.ts` - odata-mcp-proxy: https://github.com/lemaiwo/odata-mcp-proxy - CF MCP server example: https://github.com/lemaiwo/btp-cf-mcp-server - Audit log MCP server example: https://github.com/lemaiwo/btp-auditlog-mcp-server - BTP MCP server example: https://github.com/lemaiwo/btp-mcp-server ## Implementation Plan ### Phase 1: Project Scaffolding 1. Initialize CAP TypeScript project (`cds init --add typescript`) with npm workspaces 2. Set up monorepo structure — root `package.json` with workspaces: `["packages/*", "app/*"]` 3. Configure TypeScript — root `tsconfig.json` + per-package configs 4. Add `.gitignore` and initialize git repo ### Phase 2: CAP Backend + Agent 5. Define CDS data model (`db/schema.cds`) — chat sessions, messages, tool calls 6. Define CDS service (`srv/chat-service.cds`) — actions: `chat(sessionId, prompt)`, `createSession()`, entities for history 7. Implement agent (`srv/agent.ts`) — LangGraph StateGraph with AzureOpenAiChatClient, tool calling, human-in-the-loop 8. Implement MCP adapter (`srv/mcp/mcp-adapter.ts`) — MultiServerMCPClient connecting to all MCP server modules 9. Implement service handler (`srv/chat-service.ts`) — wire CDS actions to agent, handle streaming via WebSocket 10. Add AI Core service binding — configure `package.json` CDS requires for aicore destination ### Phase 3: UI5 Chat Application 11. Scaffold UI5 freestyle app (`app/chat/`) with TypeScript 12. Build chat UI — chat bubble controls, message list, input area 13. Implement chat controller — call CAP service actions, handle streaming responses 14. Configure dev-time integration — `cds-plugin-ui5` for single `cds watch` startup 15. Add `xs-app.json` routing for approuter ### Phase 4: MCP Server Modules 16. Create `packages/cf-mcp-server/` — `package.json` + `btp-cf-api-config.json` (27 entity sets for CF V3 API) 17. Create `packages/btp-mcp-server/` — `package.json` + `btp-admin-api-config.json` (4 APIs: Accounts, Entitlements, Provisioning, XSUAA) 18. Create `packages/auditlog-mcp-server/` — `package.json` + `btp-audit-log-api-config.json` 19. Create `packages/aicore-mcp-server/` — `package.json` + AI Core API config 20. Wire MCP servers to agent — configure MultiServerMCPClient to spawn each server via stdio ### Phase 5: Deployment 21. Create `mta.yaml` — CAP srv module, UI5 deployer, MCP server modules, shared services 22. Create `xs-security.json` — shared XSUAA with scopes for agent + MCP operations 23. Configure BTP destinations — CF_API, BTP services, AUDIT_LOG_SERVICE 24. Add `default-env.json` template for local development ### Phase 6: Polish 25. Add error handling — graceful MCP server failures, AI Core timeout handling 26. Add session management — persist chat history via CDS 27. Test locally — `cds watch` with mocked destinations and SQLite 28. Document — README with setup instructions ## MCP Server Config Pattern All MCP server modules follow the same zero-code pattern from odata-mcp-proxy: - Single dependency: `odata-mcp-proxy` - Single start command: `odata-mcp-proxy --config .json` - Config JSON defines server metadata, APIs (destination + pathPrefix + entitySets), and CRUD operations per entity - Same XSUAA security model (MCPViewer/MCPEditor/MCPAdmin roles) - BTP services: destination-lite, connectivity-lite, xsuaa-application ## Agent Pattern (from ai-sdk-js sample) The LangGraph agent uses: - `AzureOpenAiChatClient` from `@sap-ai-sdk/langchain` (connects to AI Core GenAI Hub) - `StateGraph` with nodes: `agent` (LLM call), `tools` (execute tool calls), `askHuman` (interrupt for input) - Conditional routing: tool_calls → tools node → agent loop; farewell → END; otherwise → askHuman - `MemorySaver` for conversation persistence - Tools from both MCP servers (via `mcpClient.getTools()`) and locally defined tools - `ToolNode` wraps all tools for the graph