cevheri commited on
Commit
c6df9a6
·
0 Parent(s):

initial commit

Browse files
.env.example ADDED
@@ -0,0 +1,9 @@
 
 
 
 
 
 
 
 
 
 
1
+ # LLM configuration for local testing
2
+ LLM_PROVIDER=OPENAI
3
+ LLM_MODEL=gpt-4.1
4
+ LLM_API_KEY=sk-proj-
5
+ # end LLM configuration
6
+
7
+ # MCP server configuration for local testing
8
+ MCP_SERVER_URL=https://dpc-restapi-mcp-server-75k7y.ondigitalocean.app/mcp/
9
+ #MCP_SERVER_URL=http://0.0.0.0:8000/mcp/
.gitignore ADDED
@@ -0,0 +1,14 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # Python-generated files
2
+ __pycache__/
3
+ *.py[oc]
4
+ build/
5
+ dist/
6
+ wheels/
7
+ *.egg-info
8
+
9
+ # Virtual environments
10
+ .venv
11
+ .env
12
+ .idea/
13
+ .vscode/
14
+ .ruff_cache/
.python-version ADDED
@@ -0,0 +1 @@
 
 
1
+ 3.13
README.md ADDED
@@ -0,0 +1,93 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # DPC MCP Client
2
+
3
+ Bu proje, LangChain MCP Client kullanarak FASTMC-Server'ın streamablehttp protokolü üzerinden Product Catalog API'lerini çağırmak için tasarlanmış bir Gradio tabanlı chatbot uygulamasıdır.
4
+
5
+ ## 🚀 Özellikler
6
+
7
+ - LangChain MCP Client entegrasyonu
8
+ - Gradio tabanlı kullanıcı arayüzü
9
+ - StreamableHTTP protokolü desteği
10
+ - Product Catalog API entegrasyonu
11
+ - Astral/UV paket yöneticisi desteği
12
+ - Python 3.13 uyumluluğu
13
+
14
+ ## 📋 Gereksinimler
15
+
16
+ - Python 3.13 veya üzeri
17
+ - UV paket yöneticisi
18
+ - Aşağıdaki çevre değişkenleri:
19
+
20
+ ```env
21
+ AGENT_DEBUG=true
22
+ LLM_PROVIDER=OPENAI
23
+ LLM_API_KEY=your_api_key_here
24
+ LLM_MODEL=your_model_name_here
25
+ MCP_SERVER_URL=your_mcp_server_url_here
26
+ ```
27
+
28
+ ## 🛠️ Kurulum
29
+
30
+ 1. Projeyi klonlayın:
31
+ ```bash
32
+ git clone https://github.com/yourusername/dpc_mcp_client.git
33
+ cd dpc_mcp_client
34
+ ```
35
+
36
+ 2. UV ile bağımlılıkları yükleyin:
37
+ ```bash
38
+ uv venv
39
+ source .venv/bin/activate # Linux/Mac
40
+ # veya
41
+ .venv\Scripts\activate # Windows
42
+ uv pip install -e .
43
+ ```
44
+
45
+ ## 🚀 Kullanım
46
+
47
+ Uygulamayı başlatmak için:
48
+
49
+ ```bash
50
+ uv run app.py
51
+ ```
52
+
53
+ Uygulama başlatıldığında, tarayıcınızda Gradio arayüzü otomatik olarak açılacaktır. Bu arayüz üzerinden Product Catalog API'lerini sorgulayabilirsiniz.
54
+
55
+ ## 📁 Proje Yapısı
56
+
57
+ ```
58
+ dpc_mcp_client/
59
+ ├── app.py # Gradio UI ve ana uygulama
60
+ ├── mcp_client.py # MCP Client implementasyonu
61
+ ├── resources/ # Kaynak dosyaları
62
+ │ ├── instruction.txt
63
+ │ └── dpc_restapi_summary.txt
64
+ ├── pyproject.toml # Proje bağımlılıkları
65
+ └── README.md
66
+ ```
67
+
68
+ ## 🔧 Bağımlılıklar
69
+
70
+ - environs>=14.2.0
71
+ - gradio>=5.32.1
72
+ - langchain-mcp-adapters>=0.1.4
73
+ - langchain-openai>=0.3.19
74
+ - langgraph>=0.4.8
75
+ - loguru>=0.7.3
76
+
77
+ ## 🤝 Katkıda Bulunma
78
+
79
+ 1. Bu depoyu fork edin
80
+ 2. Yeni bir özellik dalı oluşturun (`git checkout -b feature/amazing-feature`)
81
+ 3. Değişikliklerinizi commit edin (`git commit -m 'Add some amazing feature'`)
82
+ 4. Dalınıza push yapın (`git push origin feature/amazing-feature`)
83
+ 5. Bir Pull Request oluşturun
84
+
85
+ ## 📝 Lisans
86
+
87
+ Bu proje MIT lisansı altında lisanslanmıştır. Daha fazla bilgi için `LICENSE` dosyasına bakın.
88
+
89
+ ## 📞 İletişim
90
+
91
+ Proje Sahibi - [@yourusername](https://github.com/yourusername)
92
+
93
+ Proje Linki: [https://github.com/yourusername/dpc_mcp_client](https://github.com/yourusername/dpc_mcp_client)
app.py ADDED
@@ -0,0 +1,62 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # Gradio UI for local chatbot testing with MCP client
2
+ import logging
3
+ import asyncio
4
+ import gradio as gr
5
+
6
+ from mcp_client import MCPClient
7
+
8
+ logger = logging.getLogger(__name__)
9
+
10
+ async def initialize_client():
11
+ client = MCPClient()
12
+ await client.initialize()
13
+ return client
14
+
15
+ def launch_ui():
16
+ with gr.Blocks(title="MCP Chatbot UI", fill_height=True, fill_width=True) as demo:
17
+ gr.Markdown("## Dnext Product Catalog AI Assistant")
18
+ gr.Markdown("Please wait while the AI assistant is initializing...")
19
+
20
+ chatbot = gr.Chatbot(height=600, label="Chatbot", type="messages")
21
+ msg = gr.Textbox(
22
+ label="Enter your request",
23
+ placeholder="Type your message here...",
24
+ lines=2
25
+ )
26
+ submit_btn = gr.Button("Submit")
27
+ clear_btn = gr.Button("Clear Chat")
28
+
29
+ async def respond(user_message):
30
+ bot_response = await client.invoke(user_message)
31
+ return [
32
+ {"role": "user", "content": user_message},
33
+ {"role": "assistant", "content": bot_response}
34
+ ]
35
+
36
+ def clear_chat():
37
+ return [], []
38
+
39
+ submit_btn.click(
40
+ fn=respond,
41
+ inputs=[msg],
42
+ outputs=[chatbot]
43
+ )
44
+
45
+ clear_btn.click(
46
+ fn=clear_chat,
47
+ inputs=[],
48
+ outputs=[chatbot, msg]
49
+ )
50
+
51
+ return demo
52
+
53
+ async def main():
54
+ global client
55
+ client = await initialize_client()
56
+ demo = launch_ui()
57
+ demo.launch(share=False)
58
+
59
+ if __name__ == "__main__":
60
+ asyncio.run(main())
61
+
62
+ # uv run app.py
mcp_client.py ADDED
@@ -0,0 +1,111 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ from mcp import ClientSession
2
+ from mcp.client.streamable_http import streamablehttp_client
3
+
4
+ from langgraph.checkpoint.memory import InMemorySaver
5
+ from langgraph.prebuilt import create_react_agent
6
+ from langchain_mcp_adapters.tools import load_mcp_tools
7
+ from langchain_openai import ChatOpenAI
8
+
9
+ from environs import Env
10
+ from loguru import logger
11
+
12
+ env = Env()
13
+ env.read_env()
14
+
15
+ AGENT_DEBUG = env.bool("AGENT_DEBUG", True)
16
+ LLM_PROVIDER = env.str("LLM_PROVIDER", "OPENAI")
17
+ LLM_API_KEY = env.str("LLM_API_KEY")
18
+ LLM_MODEL = env.str("LLM_MODEL")
19
+ MCP_SERVER_URL = env.str("MCP_SERVER_URL")
20
+
21
+
22
+ def get_llm():
23
+ if LLM_PROVIDER == "OPENAI":
24
+ return ChatOpenAI(model=LLM_MODEL, api_key=LLM_API_KEY)
25
+ elif LLM_PROVIDER == "GEMINI":
26
+ raise NotImplementedError("Gemini is not supported yet")
27
+ else:
28
+ raise ValueError(f"Unsupported LLM provider: {LLM_PROVIDER}")
29
+
30
+
31
+ class MCPClient:
32
+ _instance = None
33
+
34
+ def __new__(cls):
35
+ logger.info("Creating MCP client instance...")
36
+ if cls._instance is None:
37
+ cls._instance = super(MCPClient, cls).__new__(cls)
38
+ cls._instance._initialized = False
39
+ return cls._instance
40
+
41
+ def __init__(self):
42
+ logger.info("Initializing MCP client instance...")
43
+ if self._initialized:
44
+ return
45
+
46
+ self.llm = get_llm()
47
+ self.tools = None
48
+ self.agent = None
49
+ self.instruction = ""
50
+ self.api_description = ""
51
+ self.system_message = ""
52
+ self._initialized = True
53
+ self.checkpointer = InMemorySaver()
54
+ self.load_instruction()
55
+ self.load_api_description()
56
+
57
+ def load_instruction(self) -> str:
58
+ logger.info("Loading instruction...")
59
+ try:
60
+ with open("resources/instruction.txt", "r") as file:
61
+ self.instruction = file.read()
62
+ except FileNotFoundError:
63
+ logger.error("Instruction file not found")
64
+ raise FileNotFoundError("Instruction file not found")
65
+
66
+ def load_api_description(self) -> str:
67
+ logger.info("Loading api description...")
68
+ try:
69
+ with open("resources/dpc_restapi_summary.txt", "r") as file:
70
+ self.api_description = file.read()
71
+ except FileNotFoundError:
72
+ logger.error("API description file not found")
73
+ raise FileNotFoundError("API description file not found")
74
+
75
+ async def initialize(self):
76
+ logger.info("Initializing MCP client...")
77
+ self.system_message = "".join([self.instruction, "\n\n", self.api_description])
78
+
79
+ async def invoke(self, input_messages):
80
+ logger.info(f"Invoking agent with input: {input_messages}")
81
+ async with streamablehttp_client(MCP_SERVER_URL) as (read, write, _):
82
+ async with ClientSession(read, write) as session:
83
+ await session.initialize()
84
+ logger.info("Loading tools...")
85
+ self.tools = await load_mcp_tools(session)
86
+ logger.info("Creating agent...")
87
+ self.agent = create_react_agent(
88
+ model=self.llm,
89
+ tools=self.tools,
90
+ prompt=self.system_message,
91
+ checkpointer=self.checkpointer,
92
+ debug=AGENT_DEBUG,
93
+ )
94
+ logger.info("Invoking agent...")
95
+ config = {"configurable": {"thread_id": "conversation_123"}}
96
+ result = await self.agent.ainvoke(input={"messages": input_messages}, config=config)
97
+ logger.info(f"Agent result: {result}")
98
+ logger.info("========================================================")
99
+ last_message = result["messages"][-1]
100
+ logger.info(f"Last message: {last_message.content}")
101
+ return last_message.content
102
+
103
+ # Agent result: {'messages':
104
+ # [HumanMessage(content='hi', additional_kwargs={}, response_metadata={}, id='205d9484-c4f0-4e9e-962f-218d2e82bc03'),
105
+ # AIMessage(content='This is just a greeting, so no API call is required. If you have any tasks or requests related to product catalog operations, please let me know how I can assist you!',
106
+ # additional_kwargs={'refusal': None},
107
+ # response_metadata={'token_usage': {'completion_tokens': 37, 'prompt_tokens': 27124, 'total_tokens': 27161,
108
+ # 'completion_tokens_details': {'accepted_prediction_tokens': 0, 'audio_tokens': 0, 'reasoning_tokens': 0, 'rejected_prediction_tokens': 0},
109
+ # 'prompt_tokens_details': {'audio_tokens': 0, 'cached_tokens': 27008}}, 'model_name': 'gpt-4.1-2025-04-14',
110
+ # 'system_fingerprint': 'fp_799e4ca3f1', 'id': 'chatcmpl-BejXD72NDlc9UqrJiobIA6tQbuNaj', 'service_tier': 'default', 'finish_reason': 'stop', 'logprobs': None}, id='run--dee9f47d-99f9-40a6-b8c7-241668e6ac38-0',
111
+ # usage_metadata={'input_tokens': 27124, 'output_tokens': 37, 'total_tokens': 27161, 'input_token_details': {'audio': 0, 'cache_read': 27008}, 'output_token_details': {'audio': 0, 'reasoning': 0}})]}
pyproject.toml ADDED
@@ -0,0 +1,14 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ [project]
2
+ name = "dpc-mcp-client"
3
+ version = "0.1.0"
4
+ description = "Add your description here"
5
+ readme = "README.md"
6
+ requires-python = ">=3.13"
7
+ dependencies = [
8
+ "environs>=14.2.0",
9
+ "gradio>=5.32.1",
10
+ "langchain-mcp-adapters>=0.1.4",
11
+ "langchain-openai>=0.3.19",
12
+ "langgraph>=0.4.8",
13
+ "loguru>=0.7.3",
14
+ ]
resources/dpc_restapi_summary.txt ADDED
@@ -0,0 +1,331 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ ====================================================
2
+ **API_DESCRIPTION_BEGIN** section is provided below.
3
+
4
+ **Description:** Dnext Product Catalog API, which is compliant with the TMF620 Product Catalog Management standard.
5
+ This API allows users to manage key catalog elements such as product offerings, specifications, characteristics, and pricing.
6
+ It meets TMF620 minimum requirements while incorporating Dnext-specific fields or validations.
7
+
8
+ **API Base URL:**
9
+ `https://learning.test.orbitant.dev/api/productCatalogManagement/v4`
10
+
11
+ **Allowed Constant Enum Values**: Use these valid values for specific fields when constructing tool inputs.
12
+ * **General Constant Enum Values:**
13
+ - lifecycleStatus: "In study", "In design", "In test", "Active", "Launched", "Retired", "Obsolete", "Rejected", "None"
14
+ - valueType: "string", "number", "date", "true/false", "integer", "time", "macAddress"
15
+ - unitOfMeasure: "Second", "Minute", "Hour", "Day", "Week", "Month", "Year", "M", "Mm", "Cm", "Km", "Kg", "Pound", "Bps", "Mbps", "Gbps", "Question", "Byte", "Mb", "Gb", "Tb", "None", "Address", "Color", "Duration", "Joule", "Number", "Phone Number", "Size", "Currency"
16
+ - characteristicType: "Simple Value", "Range", "Choice"
17
+ - rangeInterval: "Open", "Closed", "Closed Bottom", "Closed Top"
18
+ - relationshipType: "aggregation", "migration", "substitution", "dependency", "exclusivity"
19
+
20
+ * **ProductSpecification Constant Enum Values:**
21
+ - operationType: "add", "delete", "modify", "modify.Migration", "modify.Relocation", "modify.Takeover", "statusChange", "statusChange.Resume", "statusChange.Suspend"
22
+ - relation: "reliesOn", "uses"
23
+
24
+ * **ProductOffering Constant Enum Values:**
25
+ - operationType: same as ProductSpecification
26
+ - relation: "reliesOn"
27
+
28
+ * **ProductOfferingPrice Constant Enum Values:**
29
+ - priceType: "One time charge", "Data tariff charge", "Simple usage charge", "Recurring charge", "Per line charge", "Parametric charge", "Per contract charge", "Voice tariff charge", "Simple usage discount", "Recurring discount", "Voice tariff discount", "One time discount", "One time allowance", "Recurring allowance", "Weekend allowance", "Weekend voice allowance", "Weekend data allowance", "Data commitment", "Threshold commitment", "Usage commitment", "Penalty", "Deposit", "Cost", "Upfront payment"
30
+ - Money.unit: "ALL", "AUD", "CHF", "GBP", "EUR", "USD", "JPY", "CAD", "CNY", "HKD", "NZD", "TRY"
31
+
32
+ **Core API Entities and Their Attributes:**
33
+ **1. ProductCatalog**
34
+ * **Description:** The central organizing entity for product-related data. It groups `ProductOffering`s and `Category` objects.
35
+ * **API Endpoints:**
36
+ * `POST /productCatalog`: Create a new product catalog.
37
+ * **Fields (`ProductCatalogCreate` for POST):**
38
+ * `name` (string): **Mandatory**. The name of the catalog.
39
+ * `description` (string): Optional. Description of this catalog.
40
+ * `lifecycleStatus` (string): Optional. Used to indicate the current lifecycle status (e.g., "Active", "Retired", "Draft").
41
+ * `version` (string): Optional. Version of the catalog.
42
+ * `validFor` (`TimePeriod` object): Optional. The period for which the catalog is valid.
43
+ * `category` (array of `CategoryRef`): Optional. List of root categories contained in this catalog.
44
+ * `relatedParty` (array of `RelatedParty`): Optional. List of parties involved in this catalog.
45
+ * `@baseType`, `@schemaLocation`, `@type`: Optional meta-attributes for extension.
46
+
47
+ **2. Category**
48
+ * **Description:** Used for logically grouping product offerings. Categories can have a hierarchical structure (sub-categories).
49
+ * **API Endpoints:**
50
+ * `POST /category`: Create a new category.
51
+ * **Fields (`CategoryCreate` for POST):**
52
+ * `name` (string): **Mandatory**. The name of the category.
53
+ * `description` (string): Optional. Description of this category.
54
+ * `isRoot` (boolean): Optional. Indicates if this is a root category (default: `false`).
55
+ * `lifecycleStatus` (string): Optional. Used to indicate the current lifecycle status.
56
+ * `version` (string): Optional. Version of the category.
57
+ * `validFor` (`TimePeriod` object): Optional. The period for which the category is valid.
58
+ * `parent` (`CategoryRef` object): Optional. Reference to the parent category if this is a sub-category.
59
+ * `productCatalog` (array of `ProductCatalogRef`): Optional. References to the catalogs this category belongs to.
60
+ * `productOffering` (array of `ProductOfferingRef`): Optional. References to product offerings associated with this category.
61
+ * `relatedParty` (array of `RelatedParty`): Optional. Parties involved in this category.
62
+ * `@baseType`, `@schemaLocation`, `@type`: Optional meta-attributes.
63
+
64
+ **3. ProductCharacteristic**
65
+ * **Description:** Represents a characteristic (attribute) of a product or product specification.
66
+ * **Usage:** Typically nested within `ProductSpecification` or `ProductOffering`.
67
+ * **Fields:**
68
+ * `id` (string): Optional. Unique identifier.
69
+ * `name` (string): Optional. Name of the characteristic.
70
+ * `valueType` (string): Optional. Categorization of the value (e.g., "string", "integer", "boolean").
71
+ * `defaultValue` (object): Optional. The default value for this characteristic.
72
+ * `configurable` (boolean): Optional. True if configurable (default: false).
73
+ * `extensible` (boolean): Optional. True if extensible (default: false).
74
+ * `isUnique` (boolean): Optional. True if unique (default: false).
75
+ * `maxCardinality` (integer): Optional. Max instances.
76
+ * `minCardinality` (integer): Optional. Min instances.
77
+ * `regex` (string): Optional. Regex to validate the value.
78
+ * `validFor` (`TimePeriod` object): Optional. Period of validity.
79
+ * `productCharValue` (array of `ProductCharacteristicValue`): Optional. List of possible values.
80
+ * `@baseType`, `@schemaLocation`, `@type`: Optional meta-attributes.
81
+
82
+ **4. ProductSpecification**
83
+ * **Description:** Defines the technical details and attributes of a product or service.
84
+ * **API Endpoints:**
85
+ * `POST /productSpecification`: Create a new product specifications.
86
+ * **Fields (used when referencing or viewing):**
87
+ * `id` (string): **Mandatory** when referencing (e.g., in ProductOffering). Unique identifier.
88
+ * `href` (string): Optional. URL to the resource.
89
+ * `description` (string): Optional. Description.
90
+ * `isBundle` (boolean): Optional. True if a bundle specification.
91
+ * `lifecycleStatus` (string): Optional. Lifecycle status.
92
+ * `name` (string): Optional. Name of the specification.
93
+ * `productNumber` (string): Optional. Product number.
94
+ * `version` (string): Optional. Version.
95
+ * `validFor` (`TimePeriod` object): Optional. Period of validity.
96
+ * `productSpecCharacteristic` (array of `ProductCharacteristic`): Optional. List of characteristics for this specification.
97
+ * `serviceSpecification` (array of `ServiceSpecificationRef`): Optional. References to related service specifications.
98
+ * `resourceSpecification` (array of `ResourceSpecificationRef`): Optional. References to related resource specifications.
99
+ * `productSpecificationRelationship` (array of `ProductSpecificationRelationship`): Optional. Relationships with other specs.
100
+ * `attachment` (array of `AttachmentRefOrValue`): Optional. Related attachments.
101
+ * `relatedParty` (array of `RelatedParty`): Optional. Involved parties.
102
+ * `targetProductSchema` (`TargetProductSchema` object): Optional. Schema reference.
103
+ * `@baseType`, `@schemaLocation`, `@type`: Optional meta-attributes.
104
+
105
+ **5. ProductOfferingPrice**
106
+ * **Description:** Details the pricing information for a `ProductOffering`.
107
+ * **API Endpoints:**
108
+ * `POST /productOfferingPrice`: Create a new product offering price.
109
+ * **Fields (`ProductOfferingPriceCreate` for POST):**
110
+ * `name` (string): **Mandatory**. Name of the price (e.g., "Monthly Fee", "One-Time Setup").
111
+ * `description` (string): Optional. Description of the price.
112
+ * `priceType` (string): **Mandatory**. Type of price (e.g., "recurring", "one time", "usage").
113
+ * `validFor` (`TimePeriod` object): Optional. Period of validity for the price.
114
+ * `price` (`Money` object): **Mandatory**. The monetary value.
115
+ * `price.value` (number): **Mandatory**. Numeric price value.
116
+ * `price.unit` (string): **Mandatory**. Currency unit (e.g., "USD", "TRY").
117
+ * `recurringChargePeriod` (string): Optional. Period for recurring charges (e.g., "monthly", "annually").
118
+ * `unitOfMeasure` (`Quantity` object): Optional. Unit of measure if applicable (e.g., for usage-based).
119
+ * `taxIncluded` (boolean): Optional. True if tax is included.
120
+ * `taxRate` (number): Optional. Tax rate.
121
+ * `channel` (array of `ChannelRef`): Optional. Channels.
122
+ * `place` (array of `PlaceRef`): Optional. Places.
123
+ * `prodSpecCharValueUse` (array of `ProdSpecCharValueUse`): Optional. How characteristics influence price.
124
+ * `productOffering` (array of `ProductOfferingRef`): Optional. References to associated `ProductOffering`s.
125
+ * `productOfferingPriceRelationship` (array of `ProductOfferingPriceRelationship`): Optional. Relationships with other prices.
126
+ * `popRelationship` (array of `ProductOfferingPriceRelationship`): Optional. Alias for `productOfferingPriceRelationship`.
127
+ * `constraint` (array of `ConstraintRef`): Optional. Constraints.
128
+ * `pricingLogicAlgorithm` (array of `PricingLogicAlgorithmRef`): Optional. Pricing algorithms.
129
+ * `@baseType`, `@schemaLocation`, `@type`: Optional meta-attributes.
130
+
131
+ **6. ProductOffering**
132
+ * **Description:** Represents a product or service offered to customers, linking specifications, pricing, and catalog organization.
133
+ * **API Endpoints:**
134
+ * `POST /productOffering`: Create a new product offering.
135
+ * **Fields (`ProductOfferingCreate` for POST):**
136
+ * `name` (string): **Mandatory**. Name of the product offering.
137
+ * `description` (string): Optional. Description.
138
+ * `lifecycleStatus` (string): Optional. Lifecycle status (e.g., "Active", "Retired", "Pending").
139
+ * `statusReason` (string): Optional. Reason for current status.
140
+ * `isBundle` (boolean): Optional. True if a bundle (default: false).
141
+ * `isSellable` (boolean): Optional. True if sellable.
142
+ * `version` (string): Optional. Version.
143
+ * `validFor` (`TimePeriod` object): Optional. Period of validity.
144
+ * `category` (array of `CategoryRef`): References to categories this offering belongs to.
145
+ * `productSpecification` (`ProductSpecificationRef` object): **Mandatory**. Reference to the underlying product specification.
146
+ * `productOfferingPrice` (array of `ProductOfferingPriceRef`): Optional. References to associated prices.
147
+ * `channel` (array of `ChannelRef`): Optional. Channels.
148
+ * `place` (array of `PlaceRef`): Optional. Places.
149
+ * `agreement` (array of `AgreementRef`): Optional. Agreements.
150
+ * `bundledProductOffering` (array of `BundledProductOffering`): Optional. If `isBundle` is true, lists contained offerings.
151
+ * `resourceCandidate` (`ResourceCandidateRef` object): Optional. Resource candidate.
152
+ * `serviceCandidate` (`ServiceCandidateRef` object): Optional. Service candidate.
153
+ * `prodSpecCharValueUse` (array of `ProdSpecCharValueUse`): Optional. Defines char usage.
154
+ * `attachment` (array of `AttachmentRefOrValue`): Optional. Attachments.
155
+ * `relatedParty` (array of `RelatedParty`): Optional. Involved parties.
156
+ * `@baseType`, `@schemaLocation`, `@type`: Optional meta-attributes.
157
+
158
+ **Common Referenced Objects:**
159
+ * **`TimePeriod`:** `{ "startDateTime": "string (date-time)", "endDateTime": "string (date-time)" }`
160
+ * **`Money`:** `{ "value": "number", "unit": "string" }`
161
+ * **`Quantity`:** `{ "amount": "number", "unit": "string" }`
162
+ * **Reference Objects (`ProductCatalogRef`, `CategoryRef`, `ProductSpecificationRef`, `ProductOfferingPriceRef`, etc.):**
163
+ * Typically contain `id` (string), `href` (string), `name` (string), and `@referredType` (string).
164
+ * Example: `{"id": "some-id", "href": "path/to/resource/some-id", "name": "Resource Name", "@referredType": "ProductCatalog"}`
165
+ * **`RelatedParty`:** `{ "id": "string", "href": "string", "name": "string", "role": "string", ...}`
166
+
167
+ **Creating an Offer Process Documentation (Sequential Steps with Payloads):**
168
+ To create a complete product offer in the system, you need to follow these sequential steps, making a POST request for each. Note that the IDs generated in previous steps are often used as references in subsequent steps.
169
+
170
+ **Step 1: Create a Product Characteristic**
171
+ * **Description:** Defines a unique attribute of a product, like speed or storage.
172
+ * **Request URL:** `POST https://learning.test.orbitant.dev/api/productCatalogManagement/v4/productCharacteristic`
173
+ * **Example Payload:**
174
+ ```json
175
+ {
176
+ "characteristicType": "Simple Value",
177
+ "configurable": false,
178
+ "extensible": false,
179
+ "isUnique": false,
180
+ "isVisible": false,
181
+ "isModifiable": false,
182
+ "mandatory": false,
183
+ "minCardinality": 0,
184
+ "maxCardinality": 1,
185
+ "name": "testSaturn",
186
+ "productCharacteristicValue": [
187
+ {
188
+ "isDefault": false,
189
+ "unitOfMeasure": "MBPS",
190
+ "value": "1000",
191
+ "valueType": "string"
192
+ }
193
+ ],
194
+ "valueType": "string"
195
+ }
196
+ ```
197
+ * **Explanation:** This payload creates a characteristic named 'testSaturn' with a value of '1000 MBPS', defining its behavior (e.g., not configurable, not mandatory). You would typically obtain the `id` from the response of this call for use in subsequent steps.
198
+
199
+ **Step 2: Create a Product Offering Price**
200
+ * **Description:** Defines the pricing structure for a product, including its value, type, and unit of measure.
201
+ * **Request URL:** `POST https://learning.test.orbitant.dev/api/productCatalogManagement/v4/productOfferingPrice`
202
+ * **Example Payload:**
203
+ ```json
204
+ {
205
+ "name": "testSaturnPrice",
206
+ "version": "0",
207
+ "priceType": "One time charge",
208
+ "unitOfMeasure": {
209
+ "units": "Day",
210
+ "amount": 1
211
+ },
212
+ "recurringChargePeriodType": "monthly",
213
+ "recurringChargePeriodLength": 0,
214
+ "isBundle": false,
215
+ "lifecycleStatus": "In study",
216
+ "price": {
217
+ "value": 100,
218
+ "unit": "USD"
219
+ },
220
+ "percentage": 0
221
+ }
222
+ ```
223
+ * **Explanation:** This payload defines a one-time price of 100 USD for a product offering. It specifies the price type, currency, and any recurring charge details. You would typically obtain the `id` from the response of this call.
224
+
225
+ **Step 3: Create a Product Specification**
226
+ * **Description:** Ties product characteristics and their values together to define the technical details of a product.
227
+ * **Request URL:** `POST https://learning.test.orbitant.dev/api/productCatalogManagement/v4/productSpecification`
228
+ * **Example Payload:**
229
+ ```json
230
+ {
231
+ "name": "testSaturnSpec",
232
+ "isBundle": false,
233
+ "lifecycleStatus": "In study",
234
+ "version": "0",
235
+ "productSpecCharacteristic": [
236
+ {
237
+ "id": "GENERATED_PRODUCT_CHARACTERISTIC_ID_FROM_STEP1",
238
+ "name": "testSaturn",
239
+ "characteristicType": "Simple Value",
240
+ "valueType": "string",
241
+ "configurable": false,
242
+ "isVisible": false,
243
+ "mandatory": false,
244
+ "extensible": false,
245
+ "minCardinality": 0,
246
+ "maxCardinality": 1,
247
+ "isUnique": false,
248
+ "productSpecCharacteristicValue": [
249
+ {
250
+ "valueType": "string",
251
+ "value": "1000",
252
+ "unitOfMeasure": "MBPS",
253
+ "isDefault": false
254
+ }
255
+ ],
256
+ "@type": "ProductCharacteristic",
257
+ "@baseType": "ProductCharacteristic"
258
+ }
259
+ ]
260
+ }
261
+ ```
262
+ * **Explanation:** This payload creates a product specification. It includes the `id` of the `ProductCharacteristic` created in Step 1, associating that characteristic with this specification. You would typically obtain the `id` from the response of this call.
263
+
264
+ **Step 4: Create a Product Offering**
265
+ * **Description:** Combines the product specification and pricing to form a complete, sellable offer.
266
+ * **Request URL:** `POST https://learning.test.orbitant.dev/api/productCatalogManagement/v4/productOffering`
267
+ * **Example Payload:**
268
+ ```json
269
+ {
270
+ "name": "testSaturnOffer",
271
+ "isBundle": false,
272
+ "lastUpdate": "2025-05-28T11:57:27.670Z",
273
+ "lifecycleStatus": "In study",
274
+ "version": "0",
275
+ "isSellable": false,
276
+ "productSpecification": {
277
+ "id": "GENERATED_PRODUCT_SPECIFICATION_ID_FROM_STEP3",
278
+ "href": "/api/productCatalogManagement/v4/productSpecification/GENERATED_PRODUCT_SPECIFICATION_ID_FROM_STEP3:(version=0)",
279
+ "name": "testSaturnSpec",
280
+ "version": "0"
281
+ },
282
+ "productOfferingPrice": [
283
+ {
284
+ "id": "GENERATED_PRODUCT_OFFERING_PRICE_ID_FROM_STEP2",
285
+ "href": "/api/productCatalogManagement/v4/productOfferingPrice/GENERATED_PRODUCT_OFFERING_PRICE_ID_FROM_STEP2:(version=0)",
286
+ "name": "testSaturnPrice",
287
+ "version": "0",
288
+ "@type": "ProductOfferingPrice",
289
+ "@referredType": "Product Offering Price"
290
+ }
291
+ ],
292
+ "prodSpecCharValueUse": [
293
+ {
294
+ "productSpecCharacteristicValue": [
295
+ {
296
+ "isDefault": false,
297
+ "unitOfMeasure": "MBPS",
298
+ "value": "1000",
299
+ "valueType": "string"
300
+ }
301
+ ],
302
+ "name": "testSaturn",
303
+ "characteristicType": "Simple Value",
304
+ "valueType": "string",
305
+ "minCardinality": 0,
306
+ "maxCardinality": 1,
307
+ "productSpecification": {
308
+ "id": "GENERATED_PRODUCT_SPECIFICATION_ID_FROM_STEP3",
309
+ "href": "/api/productCatalogManagement/v4/productSpecification/GENERATED_PRODUCT_SPECIFICATION_ID_FROM_STEP3:(version=0)",
310
+ "name": "testSaturnSpec",
311
+ "version": "0"
312
+ },
313
+ "configurable": false,
314
+ "isVisible": false,
315
+ "mandatory": false
316
+ }
317
+ ],
318
+ "category": [
319
+ // MANDATORY: Add a CategoryRef here (e.g., after creating a category via /category endpoint)
320
+ // Example: {"id": "category-id", "href": "/api/productCatalogManagement/v4/category/category-id", "name": "Category Name", "@referredType": "Category"}
321
+ ],
322
+ "productCatalog": [
323
+ // MANDATORY: Add a ProductCatalogRef here (e.g., after creating a catalog via /productCatalog endpoint)
324
+ // Example: {"id": "catalog-id", "href": "/api/productCatalogManagement/v4/productCatalog/catalog-id", "name": "Catalog Name", "@referredType": "ProductCatalog"}
325
+ ]
326
+ }
327
+ ```
328
+ * **Explanation:** This payload defines the complete `ProductOffering`. It references the `ProductSpecification` (from Step 3) and `ProductOfferingPrice` (from Step 2) using their generated IDs. It also re-iterates the product characteristic details for clarity within the offer. **Crucially, it requires `category` and `productCatalog` references which would need to be created via their respective endpoints first, if not already existing.**
329
+
330
+ **API_DESCRIPTION_END**
331
+ ====================================================
resources/instruction.txt ADDED
@@ -0,0 +1,36 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # Role
2
+ You are a reasoning and planning agent that translates natural language inputs into structured API requests.
3
+
4
+ # Goal
5
+ Your goal is to interpret user prompts and return an API call plan targeting the **DNext Product Catalog Management API(TMF620)**.
6
+
7
+ # Capability
8
+ - Understand user intent expressed in natural language.
9
+ - Identify the appropriate endpoint from the TMF620 OpenAPI spec.
10
+ - Determine the correct HTTP method.
11
+ - Extract path parameters, query parameters, and body payload as needed.
12
+ - Return a structured plan (do not execute the API).
13
+ - Ask clarifying questions if critical information is missing.
14
+
15
+ # Input Format
16
+ Users will input natural language requests related to product catalog operations.
17
+
18
+ # Output Format
19
+ Respond with:
20
+ 1. A short reasoning trace (in English) that explains your decision.
21
+ 2. A structured API call in JSON with fields: `method`, `endpoint`, `path_params`, `query_params`, `payload`.
22
+
23
+ # Constraint
24
+ - Do not fabricate endpoint names or parameters.
25
+ - If unsure, ask a follow-up question.
26
+ - Do not include any irrelevant information or execute the request.
27
+
28
+ # Sample UseCase
29
+ 1- When the user asks you to create a new product offering, **use the previously stored `id` and `href` values** to populate the required links to the:
30
+ - product specification,
31
+ - product offering price,
32
+ - product characteristics
33
+
34
+ # API Description
35
+ Api description is provided below between **API_DESCRIPTION_BEGIN** and **API_DESCRIPTION_END**. Use this description to understand the API, its endpoints, and the parameters for each endpoint.
36
+
uv.lock ADDED
The diff for this file is too large to render. See raw diff