memgraph-toolbox 0.1.0__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
File without changes
File without changes
@@ -0,0 +1,98 @@
1
+ from typing import Any, Dict, List, Optional
2
+
3
+ from neo4j import GraphDatabase
4
+
5
+
6
+ class Memgraph:
7
+ """
8
+ Base Memgraph client for interacting with Memgraph database.
9
+ """
10
+
11
+ def __init__(
12
+ self,
13
+ uri: str,
14
+ username: str,
15
+ password: str,
16
+ driver_config: Optional[Dict] = None,
17
+ ):
18
+ self.driver = GraphDatabase.driver(
19
+ uri, auth=(username, password), **(driver_config or {})
20
+ )
21
+ try:
22
+ import neo4j
23
+ except ImportError:
24
+ raise ImportError(
25
+ "Could not import neo4j python package. "
26
+ "Please install it with `pip install neo4j`."
27
+ )
28
+ try:
29
+ self.driver.verify_connectivity()
30
+ except neo4j.exceptions.ServiceUnavailable:
31
+ raise ValueError(
32
+ "Could not connect to Memgraph database. "
33
+ "Please ensure that the url is correct"
34
+ )
35
+ except neo4j.exceptions.AuthError:
36
+ raise ValueError(
37
+ "Could not connect to Memgraph database. "
38
+ "Please ensure that the username and password are correct"
39
+ )
40
+
41
+ def query(self, query: str, params: dict = {}) -> List[Dict[str, Any]]:
42
+ """
43
+ Execute a Cypher query and return results as a list of dictionaries.
44
+
45
+ Args:
46
+ query: The Cypher query to execute
47
+
48
+ Returns:
49
+ List of dictionaries containing query results
50
+ """
51
+ from neo4j.exceptions import Neo4jError
52
+
53
+ try:
54
+ data, _, _ = self.driver.execute_query(
55
+ query,
56
+ parameters_=params,
57
+ )
58
+ json_data = [r.data() for r in data]
59
+ return json_data
60
+ except Neo4jError as e:
61
+ if not (
62
+ (
63
+ ( # isCallInTransactionError
64
+ e.code == "Neo.DatabaseError.Statement.ExecutionFailed"
65
+ or e.code
66
+ == "Neo.DatabaseError.Transaction.TransactionStartFailed"
67
+ )
68
+ and "in an implicit transaction" in e.message
69
+ )
70
+ or ( # isPeriodicCommitError
71
+ e.code == "Neo.ClientError.Statement.SemanticError"
72
+ and (
73
+ "in an open transaction is not possible" in e.message
74
+ or "tried to execute in an explicit transaction" in e.message
75
+ )
76
+ )
77
+ or (
78
+ e.code == "Memgraph.ClientError.MemgraphError.MemgraphError"
79
+ and ("in multicommand transactions" in e.message)
80
+ )
81
+ or (
82
+ e.code == "Memgraph.ClientError.MemgraphError.MemgraphError"
83
+ and "SchemaInfo disabled" in e.message
84
+ )
85
+ ):
86
+ raise
87
+
88
+ # fallback to allow implicit transactions
89
+ with self.driver.session() as session:
90
+ data = session.run(query, params)
91
+ json_data = [r.data() for r in data]
92
+ return json_data
93
+
94
+ def close(self) -> None:
95
+ """
96
+ Close the database connection.
97
+ """
98
+ self.driver.close()
@@ -0,0 +1,51 @@
1
+ from abc import ABC, abstractmethod
2
+ from typing import Any, Dict, List
3
+
4
+
5
+ class BaseTool(ABC):
6
+ """
7
+ Base class for all tools.
8
+ """
9
+
10
+ name: str
11
+ description: str
12
+ input_schema: Dict[str, Any]
13
+
14
+ def __init__(self, name: str, description: str, input_schema: Dict[str, Any]):
15
+ self.name = name
16
+ self.description = description
17
+ self.input_schema = input_schema
18
+
19
+ @abstractmethod
20
+ def call(self, arguments: Dict[str, Any]) -> List[Any]:
21
+ """
22
+ Execute the tool with the provided arguments.
23
+
24
+ Parameters:
25
+ arguments (dict): A dictionary of arguments as defined by the input schema.
26
+
27
+ Returns:
28
+ List containing one or more output values.
29
+ """
30
+ pass
31
+
32
+ def __repr__(self):
33
+ return f"Tool(name={self.name}, description={self.description})"
34
+
35
+ def get_name(self) -> str:
36
+ """
37
+ Get the name of the tool.
38
+
39
+ Returns:
40
+ str: The name of the tool.
41
+ """
42
+ return self.name
43
+
44
+ def get_description(self) -> str:
45
+ """
46
+ Get the description of the tool.
47
+
48
+ Returns:
49
+ str: The description of the tool.
50
+ """
51
+ return self.description
@@ -0,0 +1,41 @@
1
+ from typing import Dict, List
2
+ from .tool import BaseTool
3
+
4
+
5
+ class BaseToolkit:
6
+ """
7
+ A Toolkit for managing tools.
8
+ """
9
+
10
+ def __init__(self):
11
+ self._tools: Dict[str, BaseTool] = {}
12
+
13
+ def add_tool(self, tool: BaseTool) -> None:
14
+ """
15
+ Add a new tool in the registry.
16
+
17
+ Raises:
18
+ ValueError: If a tool with the same name is already toolkit.
19
+ """
20
+ if tool.name in self._tools:
21
+ raise ValueError(
22
+ f"Tool with name '{tool.name}' is already present in toolkit."
23
+ )
24
+ self._tools[tool.name] = tool
25
+
26
+ def get_tool(self, name: str) -> BaseTool:
27
+ """
28
+ Retrieve a tool by its name.
29
+
30
+ Raises:
31
+ ValueError: If no tool with the given name is found.
32
+ """
33
+ if name not in self._tools:
34
+ raise ValueError(f"Tool with name '{name}' not found.")
35
+ return self._tools[name]
36
+
37
+ def get_all_tools(self) -> List[BaseTool]:
38
+ """
39
+ List all added tools.
40
+ """
41
+ return list(self._tools.values())
File without changes
File without changes
@@ -0,0 +1,35 @@
1
+ from typing import Any, Dict, List
2
+
3
+ import pytest
4
+
5
+ from ..api.toolkit import BaseToolkit
6
+ from ..api.tool import BaseTool
7
+ from ..utils.logging import logger_init
8
+
9
+ logger = logger_init("test-toolkit") # Set up logger for the test
10
+
11
+
12
+ def test_toolkit():
13
+ """Test the Toolkit class."""
14
+
15
+ toolkit = BaseToolkit()
16
+
17
+ class DummyTool(BaseTool):
18
+ def __init__(self):
19
+ super().__init__(
20
+ name="dummy_tool",
21
+ description="A dummy tool for testing",
22
+ input_schema={},
23
+ )
24
+
25
+ def call(self, arguments: Dict[str, Any]) -> List[Any]:
26
+ return ["dummy_result"]
27
+
28
+ dummy_tool = DummyTool()
29
+ toolkit.add_tool(dummy_tool)
30
+
31
+ assert toolkit.get_tool("dummy_tool") == dummy_tool
32
+ assert len(toolkit.get_all_tools()) == 1
33
+
34
+ with pytest.raises(ValueError):
35
+ toolkit.add_tool(dummy_tool)
@@ -0,0 +1,193 @@
1
+ import pytest
2
+
3
+ from ..api.memgraph import Memgraph
4
+ from ..tools.betweenness_centrality import BetweennessCentralityTool
5
+ from ..tools.config import ShowConfigTool
6
+ from ..tools.constraint import ShowConstraintInfoTool
7
+ from ..tools.cypher import CypherTool
8
+ from ..tools.index import ShowIndexInfoTool
9
+ from ..tools.page_rank import PageRankTool
10
+ from ..tools.schema import ShowSchemaInfoTool
11
+ from ..tools.storage import ShowStorageInfoTool
12
+ from ..tools.trigger import ShowTriggersTool
13
+ from ..utils.logging import logger_init
14
+
15
+ logger = logger_init("test-tools")
16
+
17
+
18
+ def test_show_schema_info_tool():
19
+ """Test the ShowSchemaInfo tool."""
20
+
21
+ uri = "bolt://localhost:7687"
22
+ user = "memgraph"
23
+ password = "memgraph"
24
+
25
+ memgraph_client = Memgraph(uri=uri, username=user, password=password)
26
+
27
+ schema_tool = ShowSchemaInfoTool(db=memgraph_client)
28
+ assert "show_schema_info" in schema_tool.name
29
+
30
+ result = schema_tool.call({})
31
+
32
+ assert isinstance(result, list)
33
+ assert len(result) >= 1
34
+
35
+
36
+ def test_show_config_tool():
37
+ """Test the ShowConfig tool."""
38
+
39
+ uri = "bolt://localhost:7687"
40
+ user = "memgraph"
41
+ password = "memgraph"
42
+
43
+ memgraph_client = Memgraph(uri=uri, username=user, password=password)
44
+
45
+ config_tool = ShowConfigTool(db=memgraph_client)
46
+ assert "show_config" in config_tool.name
47
+ result = config_tool.call({})
48
+ assert isinstance(result, list)
49
+ assert len(result) >= 1
50
+
51
+
52
+ def test_index_tool():
53
+ """Test the ShowIndexInfo tool."""
54
+
55
+ uri = "bolt://localhost:7687"
56
+ user = "memgraph"
57
+ password = "memgraph"
58
+
59
+ memgraph_client = Memgraph(uri=uri, username=user, password=password)
60
+
61
+ # Create an index for testing
62
+
63
+ memgraph_client.query("CREATE INDEX ON :Person(name)")
64
+
65
+ index_tool = ShowIndexInfoTool(db=memgraph_client)
66
+ assert "show_index_info" in index_tool.name
67
+ result = index_tool.call({})
68
+
69
+ memgraph_client.query("DROP INDEX ON :Person(name)")
70
+
71
+ assert isinstance(result, list)
72
+
73
+ assert len(result) >= 1
74
+
75
+
76
+ def test_storage_tool():
77
+ """Test the ShowStorageInfo tool."""
78
+
79
+ uri = "bolt://localhost:7687"
80
+ user = "memgraph"
81
+ password = "memgraph"
82
+
83
+ memgraph_client = Memgraph(uri=uri, username=user, password=password)
84
+
85
+ storage_tool = ShowStorageInfoTool(db=memgraph_client)
86
+ assert "show_storage_info" in storage_tool.name
87
+ result = storage_tool.call({})
88
+
89
+ assert isinstance(result, list)
90
+ assert len(result) >= 1
91
+
92
+
93
+ def test_show_constraint_info_tool():
94
+ """Test the ShowConstraintInfo tool."""
95
+ uri = "bolt://localhost:7687"
96
+ user = "memgraph"
97
+ password = "memgraph"
98
+ memgraph_client = Memgraph(uri=uri, username=user, password=password)
99
+ # Create a sample constraint
100
+ memgraph_client.query("CREATE CONSTRAINT ON (n:Person) ASSERT n.id IS UNIQUE")
101
+
102
+ constraint_tool = ShowConstraintInfoTool(db=memgraph_client)
103
+ result = constraint_tool.call({})
104
+
105
+ memgraph_client.query("DROP CONSTRAINT ON (n:Person) ASSERT n.id IS UNIQUE")
106
+
107
+ assert isinstance(result, list)
108
+ assert len(result) > 0
109
+
110
+
111
+ def test_show_triggers_tool():
112
+ """Test the ShowTriggers tool."""
113
+
114
+ uri = "bolt://localhost:7687"
115
+ user = "memgraph"
116
+ password = "memgraph"
117
+ memgraph_client = Memgraph(uri=uri, username=user, password=password)
118
+
119
+ memgraph_client.query(
120
+ """
121
+ CREATE TRIGGER my_trigger ON () CREATE AFTER COMMIT EXECUTE
122
+ UNWIND createdVertices AS newNodes
123
+ SET newNodes.created = timestamp();
124
+ """
125
+ )
126
+
127
+ trigger_tool = ShowTriggersTool(db=memgraph_client)
128
+ result = trigger_tool.call({})
129
+
130
+ memgraph_client.query("DROP TRIGGER my_trigger;")
131
+
132
+ assert isinstance(result, list)
133
+ assert len(result) > 0
134
+
135
+
136
+ def test_page_rank():
137
+ """Test the PageRank tool."""
138
+
139
+ uri = "bolt://localhost:7687"
140
+ user = "memgraph"
141
+ password = "memgraph"
142
+ memgraph_client = Memgraph(uri=uri, username=user, password=password)
143
+
144
+ # Create a sample graph for testing
145
+ memgraph_client.query(
146
+ """UNWIND range(1, 10) AS i
147
+ CREATE (:Test {id: i})-[:LINK]->(:Test {id: i + 1});
148
+ """
149
+ )
150
+
151
+ # Run the PageRank tool
152
+ page_rank_tool = PageRankTool(db=memgraph_client)
153
+ result = page_rank_tool.call({"limit": 20})
154
+ assert isinstance(result, list)
155
+ assert len(result) > 0
156
+
157
+
158
+ def test_cypher():
159
+ """Test the Cypher tool."""
160
+
161
+ uri = "bolt://localhost:7687"
162
+ user = "memgraph"
163
+ password = "memgraph"
164
+ memgraph_client = Memgraph(uri=uri, username=user, password=password)
165
+
166
+ cypher_tool = CypherTool(db=memgraph_client)
167
+ result = cypher_tool.call({"query": "RETURN 0;"})
168
+ assert isinstance(result, list)
169
+ assert len(result) == 1
170
+
171
+
172
+ def test_betweenness_centrality_tool():
173
+ """Test the RunBetweennessCentralityTool."""
174
+
175
+ uri = "bolt://localhost:7687"
176
+ user = "memgraph"
177
+ password = "memgraph"
178
+ memgraph_client = Memgraph(uri=uri, username=user, password=password)
179
+
180
+ memgraph_client.query(
181
+ """
182
+ UNWIND range(1, 5) AS i
183
+ CREATE (a:Node {id: i})-[:RELATES]->(b:Node {id: i + 1});
184
+ """
185
+ )
186
+
187
+ betweenness_tool = BetweennessCentralityTool(db=memgraph_client)
188
+ result = betweenness_tool.call({"isDirectionIgnored": True, "limit": 5})
189
+
190
+ assert isinstance(result, list)
191
+ assert len(result) > 0
192
+ assert "node" in result[0]
193
+ assert "betweenness_centrality" in result[0]
File without changes
@@ -0,0 +1,57 @@
1
+ from typing import Any, Dict, List
2
+
3
+ from ..api.memgraph import Memgraph
4
+ from ..api.tool import BaseTool
5
+
6
+
7
+ class BetweennessCentralityTool(BaseTool):
8
+ """
9
+ Tool for calculating betweenness centrality on a graph in Memgraph.
10
+ """
11
+
12
+ def __init__(self, db: Memgraph):
13
+ super().__init__(
14
+ name="run_betweenness_centrality",
15
+ description=(
16
+ "Calculates betweenness centrality for nodes in a graph. "
17
+ "Betweenness centrality measures the importance of a node based on how frequently "
18
+ "it lies on the shortest paths between other nodes, indicating its influence on "
19
+ "information flow within the network."
20
+ ),
21
+ input_schema={
22
+ "type": "object",
23
+ "properties": {
24
+ "isDirectionIgnored": {
25
+ "type": "boolean",
26
+ "description": "Set to false to consider the direction of relationships. Default is true.",
27
+ "default": True,
28
+ },
29
+ "limit": {
30
+ "type": "integer",
31
+ "description": "Limit the number of nodes to return. Default is 10.",
32
+ "default": 10,
33
+ },
34
+ },
35
+ "required": [],
36
+ },
37
+ )
38
+ self.db = db
39
+
40
+ def call(self, arguments: Dict[str, Any]) -> List[Dict[str, Any]]:
41
+ """Execute the betweenness centrality algorithm and return the results."""
42
+ is_direction_ignored = arguments.get("isDirectionIgnored", True)
43
+ limit = arguments.get("limit", 10)
44
+
45
+ query = (
46
+ "CALL betweenness_centrality.get($directed, True) "
47
+ "YIELD node, betweenness_centrality "
48
+ "RETURN node, betweenness_centrality "
49
+ "ORDER BY betweenness_centrality DESC "
50
+ "LIMIT $limit"
51
+ )
52
+ params = {"directed": not is_direction_ignored, "limit": limit}
53
+
54
+ results = self.db.query(query, params)
55
+
56
+ # Convert the results to a list of dictionaries
57
+ return results
@@ -0,0 +1,23 @@
1
+ from typing import Any, Dict, List
2
+
3
+ from ..api.memgraph import Memgraph
4
+ from ..api.tool import BaseTool
5
+
6
+
7
+ class ShowConfigTool(BaseTool):
8
+ """
9
+ Tool for showing configuration information from Memgraph.
10
+ """
11
+
12
+ def __init__(self, db: Memgraph):
13
+ super().__init__(
14
+ name="show_config",
15
+ description="Shows configuration information from a Memgraph database",
16
+ input_schema={"type": "object", "properties": {}, "required": []},
17
+ )
18
+ self.db = db
19
+
20
+ def call(self, arguments: Dict[str, Any]) -> List[Dict[str, Any]]:
21
+ """Execute the SHOW CONFIG query and return the results."""
22
+ config_info = self.db.query("SHOW CONFIG")
23
+ return config_info
@@ -0,0 +1,23 @@
1
+ from typing import Any, Dict, List
2
+
3
+ from ..api.memgraph import Memgraph
4
+ from ..api.tool import BaseTool
5
+
6
+
7
+ class ShowConstraintInfoTool(BaseTool):
8
+ """
9
+ Tool for showing constraint information from Memgraph.
10
+ """
11
+
12
+ def __init__(self, db: Memgraph):
13
+ super().__init__(
14
+ name="show_constraint_info",
15
+ description="Shows constraint information from a Memgraph database",
16
+ input_schema={"type": "object", "properties": {}, "required": []},
17
+ )
18
+ self.db = db
19
+
20
+ def call(self, arguments: Dict[str, Any]) -> List[Dict[str, Any]]:
21
+ """Execute the SHOW CONSTRAINT INFO query and return the results."""
22
+ constraint_info = self.db.query("SHOW CONSTRAINT INFO")
23
+ return constraint_info
@@ -0,0 +1,33 @@
1
+ from typing import Any, Dict, List
2
+
3
+ from ..api.memgraph import Memgraph
4
+ from ..api.tool import BaseTool
5
+
6
+
7
+ class CypherTool(BaseTool):
8
+ """
9
+ Tool for running arbitrary Cypher queries on Memgraph.
10
+ """
11
+
12
+ def __init__(self, db: Memgraph):
13
+ super().__init__(
14
+ name="run_cypher",
15
+ description="Executes a Cypher query on a Memgraph database",
16
+ input_schema={
17
+ "type": "object",
18
+ "properties": {
19
+ "query": {
20
+ "type": "string",
21
+ "description": "The Cypher query to execute",
22
+ }
23
+ },
24
+ "required": ["query"],
25
+ },
26
+ )
27
+ self.db = db
28
+
29
+ def call(self, arguments: Dict[str, Any]) -> List[Dict[str, Any]]:
30
+ """Execute the provided Cypher query and return the results."""
31
+ query = arguments["query"]
32
+ result = self.db.query(query)
33
+ return [dict(record) for record in result]
@@ -0,0 +1,23 @@
1
+ from typing import Any, Dict, List
2
+
3
+ from ..api.memgraph import Memgraph
4
+ from ..api.tool import BaseTool
5
+
6
+
7
+ class ShowIndexInfoTool(BaseTool):
8
+ """
9
+ Tool for showing index information in Memgraph.
10
+ """
11
+
12
+ def __init__(self, db: Memgraph):
13
+ super().__init__(
14
+ name="show_index_info",
15
+ description="Shows index information from a Memgraph database",
16
+ input_schema={"type": "object", "properties": {}, "required": []},
17
+ )
18
+ self.db = db
19
+
20
+ def call(self, arguments: Dict[str, Any]) -> List[Dict[str, Any]]:
21
+ """Execute the SHOW INDEX INFO query and return the results."""
22
+ index_info = self.db.query("SHOW INDEX INFO")
23
+ return index_info
@@ -0,0 +1,43 @@
1
+ from typing import Any, Dict, List
2
+
3
+ from ..api.memgraph import Memgraph
4
+ from ..api.tool import BaseTool
5
+
6
+
7
+ class PageRankTool(BaseTool):
8
+ """
9
+ Tool for calculating PageRank on a graph in Memgraph.
10
+ """
11
+
12
+ def __init__(self, db: Memgraph):
13
+ super().__init__(
14
+ name="pagerank",
15
+ description="Calculates PageRank on a graph in Memgraph",
16
+ input_schema={
17
+ "type": "object",
18
+ "properties": {
19
+ "limit": {
20
+ "type": "integer",
21
+ "description": "Number of nodes to return ",
22
+ "default": 10,
23
+ },
24
+ },
25
+ "required": [],
26
+ },
27
+ )
28
+ self.db = db
29
+
30
+ # TODO:(@antejavor) This will fail if user is not running Memgraph Mage since memgraph does not have this built in.
31
+ def call(self, arguments: Dict[str, Any]) -> List[Dict[str, Any]]:
32
+ """Execute the PageRank algorithm and return the results."""
33
+ limit = arguments.get("limit", 20)
34
+
35
+ query = f"""
36
+ CALL pagerank.get()
37
+ YIELD node, rank
38
+ RETURN node, rank
39
+ ORDER BY rank DESC LIMIT {limit}
40
+ """
41
+ pagerank_results = self.db.query(query)
42
+
43
+ return pagerank_results
@@ -0,0 +1,22 @@
1
+ from typing import Any, Dict, List
2
+
3
+ from ..api.memgraph import Memgraph
4
+ from ..api.tool import BaseTool
5
+
6
+
7
+ class ShowSchemaInfoTool(BaseTool):
8
+ """
9
+ Tool for showing schema information from Memgraph.
10
+ """
11
+
12
+ def __init__(self, db: Memgraph):
13
+ super().__init__(
14
+ name="show_schema_info",
15
+ description="Shows schema information from a Memgraph database",
16
+ input_schema={"type": "object", "properties": {}, "required": []},
17
+ )
18
+ self.db = db
19
+
20
+ def call(self, arguments: Dict[str, Any]) -> List[Dict[str, Any]]:
21
+ schema_info = self.db.query("SHOW SCHEMA INFO")
22
+ return schema_info
@@ -0,0 +1,23 @@
1
+ from typing import Any, Dict, List
2
+
3
+ from ..api.memgraph import Memgraph
4
+ from ..api.tool import BaseTool
5
+
6
+
7
+ class ShowStorageInfoTool(BaseTool):
8
+ """
9
+ Tool for showing storage information from Memgraph.
10
+ """
11
+
12
+ def __init__(self, db: Memgraph):
13
+ super().__init__(
14
+ name="show_storage_info",
15
+ description="Shows storage information from a Memgraph database",
16
+ input_schema={"type": "object", "properties": {}, "required": []},
17
+ )
18
+ self.db = db
19
+
20
+ def call(self, arguments: Dict[str, Any]) -> List[Dict[str, Any]]:
21
+ """Execute the SHOW STORAGE INFO query and return the results."""
22
+ storage_info = self.db.query("SHOW STORAGE INFO")
23
+ return storage_info
@@ -0,0 +1,23 @@
1
+ from typing import Any, Dict, List
2
+
3
+ from ..api.memgraph import Memgraph
4
+ from ..api.tool import BaseTool
5
+
6
+
7
+ class ShowTriggersTool(BaseTool):
8
+ """
9
+ Tool for showing trigger information from Memgraph.
10
+ """
11
+
12
+ def __init__(self, db: Memgraph):
13
+ super().__init__(
14
+ name="show_triggers",
15
+ description="Shows trigger information from a Memgraph database",
16
+ input_schema={"type": "object", "properties": {}, "required": []},
17
+ )
18
+ self.db = db
19
+
20
+ def call(self, arguments: Dict[str, Any]) -> List[Dict[str, Any]]:
21
+ """Execute the SHOW TRIGGERS query and return the results."""
22
+ trigger_info = self.db.query("SHOW TRIGGERS")
23
+ return trigger_info
@@ -0,0 +1,15 @@
1
+ import logging
2
+
3
+
4
+ def logger_init(name: str) -> logging.Logger:
5
+ """Set up a logger with a consistent configuration."""
6
+ logger = logging.getLogger(name)
7
+ if not logger.hasHandlers():
8
+ handler = logging.StreamHandler()
9
+ formatter = logging.Formatter(
10
+ "%(asctime)s - %(name)s - %(levelname)s - %(message)s"
11
+ )
12
+ handler.setFormatter(formatter)
13
+ logger.addHandler(handler)
14
+ logger.setLevel(logging.INFO)
15
+ return logger
@@ -0,0 +1,80 @@
1
+ Metadata-Version: 2.4
2
+ Name: memgraph-toolbox
3
+ Version: 0.1.0
4
+ Summary: Memgraph toolbox library for Memgraph AI tools and utilities
5
+ Author-email: antejavor <ante.javor@memgraph.io>
6
+ License: MIT
7
+ License-File: LICENSE
8
+ Keywords: ai,graph,memgraph,toolkit
9
+ Classifier: Intended Audience :: Developers
10
+ Classifier: License :: OSI Approved :: MIT License
11
+ Classifier: Programming Language :: Python :: 3
12
+ Classifier: Programming Language :: Python :: 3.10
13
+ Classifier: Programming Language :: Python :: 3.11
14
+ Classifier: Programming Language :: Python :: 3.12
15
+ Requires-Python: >=3.10
16
+ Provides-Extra: test
17
+ Requires-Dist: pytest-asyncio>=0.26.0; extra == 'test'
18
+ Requires-Dist: pytest>=8.3.5; extra == 'test'
19
+ Description-Content-Type: text/markdown
20
+
21
+ # Memgraph Toolbox
22
+
23
+ The **Memgraph Toolbox** is a collection of tools designed to interact with a
24
+ Memgraph database. These tools provide functionality for querying, analyzing,
25
+ and managing data within Memgraph, making it easier to work with graph data.
26
+ They are made to be easily called from other framework implementations such as
27
+ **MCP**, **Langchain** or **Lamaindex**.
28
+
29
+ ## Available Tools
30
+
31
+ Below is a list of tools included in the toolbox, along with their descriptions:
32
+
33
+ 1. `ShowTriggersTool` - Shows trigger information from a Memgraph database.
34
+ 2. `ShowStorageInfoTool` - Shows storage information from a Memgraph database.
35
+ 3. `ShowSchemaInfoTool` - Shows schema information from a Memgraph database.
36
+ 4. `PageRankTool` - Calculates PageRank on a graph in Memgraph.
37
+ 5. `ShowIndexInfoTool` - Shows index information from a Memgraph database.
38
+ 6. `CypherTool` - Executes arbitrary Cypher queries on a Memgraph database.
39
+ 7. `ShowConstraintInfoTool` - Shows constraint information from a Memgraph database.
40
+ 8. `ShowConfigTool` - Shows configuration information from a Memgraph database.
41
+ 9. `BetweennessCentralityTool` - Calculates betweenness centrality for nodes in a graph.
42
+
43
+ ## Usage
44
+
45
+ Each tool is implemented as a Python class inheriting from `BaseTool`. To use a
46
+ tool:
47
+
48
+ 1. Instantiate the tool with a `Memgraph` database connection.
49
+ 2. Call the `call` method with the required arguments.
50
+
51
+ Example:
52
+
53
+ ```python
54
+ from memgraph_toolbox.tools.trigger import ShowTriggersTool
55
+ from memgraph_toolbox.api.memgraph import Memgraph
56
+
57
+ # Connect to Memgraph
58
+ db = Memgraph()
59
+
60
+ # Use the ShowTriggersTool
61
+ tool = ShowTriggersTool(db)
62
+ triggers = tool.call({})
63
+ print(triggers)
64
+ ```
65
+
66
+ ## Requirements
67
+
68
+ - Python 3.10+
69
+ - Memgraph database
70
+ - Memgraph Mage (for certain tools like `pagerank` and `run_betweenness_centrality`)
71
+
72
+ ## Contributing
73
+
74
+ Contributions are welcome! Feel free to submit issues or pull requests to
75
+ improve the toolbox.
76
+
77
+ ## License
78
+
79
+ This project is licensed under the MIT License. See the `LICENSE` file for
80
+ details.
@@ -0,0 +1,24 @@
1
+ memgraph_toolbox/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
2
+ memgraph_toolbox/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
3
+ memgraph_toolbox/api/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
4
+ memgraph_toolbox/api/memgraph.py,sha256=YjEEvOr4-aY05GxQLmyNZUNnAU9z8yJw98GvI3FdICE,3272
5
+ memgraph_toolbox/api/tool.py,sha256=SqOCivE2NsqUrcCFyDxPOdc5nJQoSCVFfN_79rGMgEA,1222
6
+ memgraph_toolbox/api/toolkit.py,sha256=yF4FI56jpK6q1T9b3ObeO28brmuVsg4WXrWCPrngbI8,1072
7
+ memgraph_toolbox/tests/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
8
+ memgraph_toolbox/tests/test_toolkit.py,sha256=cJIyjSYf5Da1tEry1BNaggiiXwyfTCl2HIQ2a6sFKTQ,882
9
+ memgraph_toolbox/tests/test_tools.py,sha256=IUiqf5k8MA8s5LUUHwnan7_htSMY1w3zrCKYMVc5BjQ,5363
10
+ memgraph_toolbox/tools/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
11
+ memgraph_toolbox/tools/betweenness_centrality.py,sha256=QJIOob8i3N1W9TC4Rdlzs2-ucvzW6jd7YE7LdyVTLK0,2149
12
+ memgraph_toolbox/tools/config.py,sha256=J-41yKzygAVwolpi3jxqjHsGxANwPeWaNhrNgd2cpd0,725
13
+ memgraph_toolbox/tools/constraint.py,sha256=Yeh466Xu0PChl1qCHMD44NkQkb8_ovU7Nff14fgT6P0,762
14
+ memgraph_toolbox/tools/cypher.py,sha256=rJreW2_ePgMelNNgC-GIwITDSyy3-mxmHBACDou--Y8,1009
15
+ memgraph_toolbox/tools/index.py,sha256=g95oD5Y2hHgpNreIaruGdcLAnyq9mUdhZe1xaVclHtg,720
16
+ memgraph_toolbox/tools/page_rank.py,sha256=jb8KxDr9nR4rzfWrT79u80plCMAe2qDBFvWcEMsvlbw,1328
17
+ memgraph_toolbox/tools/schema.py,sha256=k7fqwBdFi33SlPo4OmFthjgH1SJr5PPsrwgrqKMHMks,657
18
+ memgraph_toolbox/tools/storage.py,sha256=1gp7fR7Rggf2ftAMqAtFGGTq4AG_gc-6vvwlkSY8Usg,738
19
+ memgraph_toolbox/tools/trigger.py,sha256=gtUocBOYZsgzVqU0yYGbVUFE45d5f2YnPXjG3kC5PBQ,723
20
+ memgraph_toolbox/utils/logging.py,sha256=Tvrtfwq4n9mkmyj4p0lJfOACIVZzWOddNvx376Ycm5Y,481
21
+ memgraph_toolbox-0.1.0.dist-info/METADATA,sha256=TUyyE_S8PLVxGSqU3HCeo-WRcieXXrB_rG8W8O8ikBQ,2746
22
+ memgraph_toolbox-0.1.0.dist-info/WHEEL,sha256=qtCwoSJWgHk21S1Kb4ihdzI2rlJ1ZKaIurTj_ngOhyQ,87
23
+ memgraph_toolbox-0.1.0.dist-info/licenses/LICENSE,sha256=Zs4MZAXqusfO2KGQoAOuIqEUtojbyIYIkiJQ0BTt45o,1065
24
+ memgraph_toolbox-0.1.0.dist-info/RECORD,,
@@ -0,0 +1,4 @@
1
+ Wheel-Version: 1.0
2
+ Generator: hatchling 1.27.0
3
+ Root-Is-Purelib: true
4
+ Tag: py3-none-any
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2025 Memgraph
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.